diff options
Diffstat (limited to 'fs')
414 files changed, 6580 insertions, 10574 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index a9b6301a04fc..90419715c7e9 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
@@ -136,7 +136,8 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) | |||
136 | } | 136 | } |
137 | 137 | ||
138 | /** | 138 | /** |
139 | * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it | 139 | * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and |
140 | * release it | ||
140 | * @dentry: dentry to look for fid in | 141 | * @dentry: dentry to look for fid in |
141 | * | 142 | * |
142 | * find a fid in the dentry and then clone to a new private fid | 143 | * find a fid in the dentry and then clone to a new private fid |
diff --git a/fs/9p/mux.c b/fs/9p/mux.c index 147ceef8e537..c783874a9caf 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c | |||
@@ -256,7 +256,7 @@ static void v9fs_mux_poll_stop(struct v9fs_mux_data *m) | |||
256 | vpt->muxnum--; | 256 | vpt->muxnum--; |
257 | if (!vpt->muxnum) { | 257 | if (!vpt->muxnum) { |
258 | dprintk(DEBUG_MUX, "destroy proc %p\n", vpt); | 258 | dprintk(DEBUG_MUX, "destroy proc %p\n", vpt); |
259 | send_sig(SIGKILL, vpt->task, 1); | 259 | kthread_stop(vpt->task); |
260 | vpt->task = NULL; | 260 | vpt->task = NULL; |
261 | v9fs_mux_poll_task_num--; | 261 | v9fs_mux_poll_task_num--; |
262 | } | 262 | } |
@@ -438,11 +438,8 @@ static int v9fs_poll_proc(void *a) | |||
438 | 438 | ||
439 | vpt = a; | 439 | vpt = a; |
440 | dprintk(DEBUG_MUX, "start %p %p\n", current, vpt); | 440 | dprintk(DEBUG_MUX, "start %p %p\n", current, vpt); |
441 | allow_signal(SIGKILL); | ||
442 | while (!kthread_should_stop()) { | 441 | while (!kthread_should_stop()) { |
443 | set_current_state(TASK_INTERRUPTIBLE); | 442 | set_current_state(TASK_INTERRUPTIBLE); |
444 | if (signal_pending(current)) | ||
445 | break; | ||
446 | 443 | ||
447 | list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) { | 444 | list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) { |
448 | v9fs_poll_mux(m); | 445 | v9fs_poll_mux(m); |
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index d9b561ba5e58..6ad6f192b6e4 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -53,6 +53,8 @@ enum { | |||
53 | Opt_uname, Opt_remotename, | 53 | Opt_uname, Opt_remotename, |
54 | /* Options that take no arguments */ | 54 | /* Options that take no arguments */ |
55 | Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, | 55 | Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, |
56 | /* Cache options */ | ||
57 | Opt_cache_loose, | ||
56 | /* Error token */ | 58 | /* Error token */ |
57 | Opt_err | 59 | Opt_err |
58 | }; | 60 | }; |
@@ -76,6 +78,8 @@ static match_table_t tokens = { | |||
76 | {Opt_fd, "fd"}, | 78 | {Opt_fd, "fd"}, |
77 | {Opt_legacy, "noextend"}, | 79 | {Opt_legacy, "noextend"}, |
78 | {Opt_nodevmap, "nodevmap"}, | 80 | {Opt_nodevmap, "nodevmap"}, |
81 | {Opt_cache_loose, "cache=loose"}, | ||
82 | {Opt_cache_loose, "loose"}, | ||
79 | {Opt_err, NULL} | 83 | {Opt_err, NULL} |
80 | }; | 84 | }; |
81 | 85 | ||
@@ -106,6 +110,7 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) | |||
106 | v9ses->debug = 0; | 110 | v9ses->debug = 0; |
107 | v9ses->rfdno = ~0; | 111 | v9ses->rfdno = ~0; |
108 | v9ses->wfdno = ~0; | 112 | v9ses->wfdno = ~0; |
113 | v9ses->cache = 0; | ||
109 | 114 | ||
110 | if (!options) | 115 | if (!options) |
111 | return; | 116 | return; |
@@ -121,7 +126,6 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) | |||
121 | "integer field, but no integer?\n"); | 126 | "integer field, but no integer?\n"); |
122 | continue; | 127 | continue; |
123 | } | 128 | } |
124 | |||
125 | } | 129 | } |
126 | switch (token) { | 130 | switch (token) { |
127 | case Opt_port: | 131 | case Opt_port: |
@@ -169,6 +173,9 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) | |||
169 | case Opt_nodevmap: | 173 | case Opt_nodevmap: |
170 | v9ses->nodev = 1; | 174 | v9ses->nodev = 1; |
171 | break; | 175 | break; |
176 | case Opt_cache_loose: | ||
177 | v9ses->cache = CACHE_LOOSE; | ||
178 | break; | ||
172 | default: | 179 | default: |
173 | continue; | 180 | continue; |
174 | } | 181 | } |
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index c134d104cb28..820bf5ca35d8 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h | |||
@@ -47,7 +47,7 @@ struct v9fs_session_info { | |||
47 | unsigned int afid; /* authentication fid */ | 47 | unsigned int afid; /* authentication fid */ |
48 | unsigned int rfdno; /* read file descriptor number */ | 48 | unsigned int rfdno; /* read file descriptor number */ |
49 | unsigned int wfdno; /* write file descriptor number */ | 49 | unsigned int wfdno; /* write file descriptor number */ |
50 | 50 | unsigned int cache; /* cache mode */ | |
51 | 51 | ||
52 | char *name; /* user name to mount as */ | 52 | char *name; /* user name to mount as */ |
53 | char *remotename; /* name of remote hierarchy being mounted */ | 53 | char *remotename; /* name of remote hierarchy being mounted */ |
@@ -73,6 +73,13 @@ enum { | |||
73 | PROTO_FD, | 73 | PROTO_FD, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | /* possible values of ->cache */ | ||
77 | /* eventually support loose, tight, time, session, default always none */ | ||
78 | enum { | ||
79 | CACHE_NONE, /* default */ | ||
80 | CACHE_LOOSE, /* no consistency */ | ||
81 | }; | ||
82 | |||
76 | extern struct dentry *v9fs_debugfs_root; | 83 | extern struct dentry *v9fs_debugfs_root; |
77 | 84 | ||
78 | int v9fs_session_init(struct v9fs_session_info *, const char *, char *); | 85 | int v9fs_session_init(struct v9fs_session_info *, const char *, char *); |
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 450b0c1b385e..8ada4c5c5d70 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
@@ -40,8 +40,10 @@ | |||
40 | extern struct file_system_type v9fs_fs_type; | 40 | extern struct file_system_type v9fs_fs_type; |
41 | extern const struct address_space_operations v9fs_addr_operations; | 41 | extern const struct address_space_operations v9fs_addr_operations; |
42 | extern const struct file_operations v9fs_file_operations; | 42 | extern const struct file_operations v9fs_file_operations; |
43 | extern const struct file_operations v9fs_cached_file_operations; | ||
43 | extern const struct file_operations v9fs_dir_operations; | 44 | extern const struct file_operations v9fs_dir_operations; |
44 | extern struct dentry_operations v9fs_dentry_operations; | 45 | extern struct dentry_operations v9fs_dentry_operations; |
46 | extern struct dentry_operations v9fs_cached_dentry_operations; | ||
45 | 47 | ||
46 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); | 48 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); |
47 | ino_t v9fs_qid2ino(struct v9fs_qid *qid); | 49 | ino_t v9fs_qid2ino(struct v9fs_qid *qid); |
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index cc24abf232d5..bed48fa96521 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c | |||
@@ -63,6 +63,8 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page) | |||
63 | int total = 0; | 63 | int total = 0; |
64 | int result = 0; | 64 | int result = 0; |
65 | 65 | ||
66 | dprintk(DEBUG_VFS, "\n"); | ||
67 | |||
66 | buffer = kmap(page); | 68 | buffer = kmap(page); |
67 | do { | 69 | do { |
68 | if (count < rsize) | 70 | if (count < rsize) |
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 062daa6000ab..ddffd8aa902d 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c | |||
@@ -53,10 +53,31 @@ | |||
53 | static int v9fs_dentry_delete(struct dentry *dentry) | 53 | static int v9fs_dentry_delete(struct dentry *dentry) |
54 | { | 54 | { |
55 | dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); | 55 | dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
56 | |||
56 | return 1; | 57 | return 1; |
57 | } | 58 | } |
58 | 59 | ||
59 | /** | 60 | /** |
61 | * v9fs_cached_dentry_delete - called when dentry refcount equals 0 | ||
62 | * @dentry: dentry in question | ||
63 | * | ||
64 | * Only return 1 if our inode is invalid. Only non-synthetic files | ||
65 | * (ones without mtime == 0) should be calling this function. | ||
66 | * | ||
67 | */ | ||
68 | |||
69 | static int v9fs_cached_dentry_delete(struct dentry *dentry) | ||
70 | { | ||
71 | struct inode *inode = dentry->d_inode; | ||
72 | dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); | ||
73 | |||
74 | if(!inode) | ||
75 | return 1; | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | /** | ||
60 | * v9fs_dentry_release - called when dentry is going to be freed | 81 | * v9fs_dentry_release - called when dentry is going to be freed |
61 | * @dentry: dentry that is being release | 82 | * @dentry: dentry that is being release |
62 | * | 83 | * |
@@ -87,6 +108,11 @@ void v9fs_dentry_release(struct dentry *dentry) | |||
87 | } | 108 | } |
88 | } | 109 | } |
89 | 110 | ||
111 | struct dentry_operations v9fs_cached_dentry_operations = { | ||
112 | .d_delete = v9fs_cached_dentry_delete, | ||
113 | .d_release = v9fs_dentry_release, | ||
114 | }; | ||
115 | |||
90 | struct dentry_operations v9fs_dentry_operations = { | 116 | struct dentry_operations v9fs_dentry_operations = { |
91 | .d_delete = v9fs_dentry_delete, | 117 | .d_delete = v9fs_dentry_delete, |
92 | .d_release = v9fs_dentry_release, | 118 | .d_release = v9fs_dentry_release, |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 9f17b0cacdd0..653dfa5b2531 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -79,6 +79,13 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
79 | vfid->filp = file; | 79 | vfid->filp = file; |
80 | kfree(fcall); | 80 | kfree(fcall); |
81 | 81 | ||
82 | if((vfid->qid.version) && (v9ses->cache)) { | ||
83 | dprintk(DEBUG_VFS, "cached"); | ||
84 | /* enable cached file options */ | ||
85 | if(file->f_op == &v9fs_file_operations) | ||
86 | file->f_op = &v9fs_cached_file_operations; | ||
87 | } | ||
88 | |||
82 | return 0; | 89 | return 0; |
83 | 90 | ||
84 | Clunk_Fid: | 91 | Clunk_Fid: |
@@ -110,7 +117,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
110 | 117 | ||
111 | if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { | 118 | if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { |
112 | filemap_write_and_wait(inode->i_mapping); | 119 | filemap_write_and_wait(inode->i_mapping); |
113 | invalidate_inode_pages(&inode->i_data); | 120 | invalidate_mapping_pages(&inode->i_data, 0, -1); |
114 | } | 121 | } |
115 | 122 | ||
116 | return res; | 123 | return res; |
@@ -234,10 +241,21 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
234 | total += result; | 241 | total += result; |
235 | } while (count); | 242 | } while (count); |
236 | 243 | ||
237 | invalidate_inode_pages2(inode->i_mapping); | 244 | invalidate_inode_pages2(inode->i_mapping); |
238 | return total; | 245 | return total; |
239 | } | 246 | } |
240 | 247 | ||
248 | const struct file_operations v9fs_cached_file_operations = { | ||
249 | .llseek = generic_file_llseek, | ||
250 | .read = do_sync_read, | ||
251 | .aio_read = generic_file_aio_read, | ||
252 | .write = v9fs_file_write, | ||
253 | .open = v9fs_file_open, | ||
254 | .release = v9fs_dir_release, | ||
255 | .lock = v9fs_file_lock, | ||
256 | .mmap = generic_file_mmap, | ||
257 | }; | ||
258 | |||
241 | const struct file_operations v9fs_file_operations = { | 259 | const struct file_operations v9fs_file_operations = { |
242 | .llseek = generic_file_llseek, | 260 | .llseek = generic_file_llseek, |
243 | .read = v9fs_file_read, | 261 | .read = v9fs_file_read, |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 9109ba1d6969..124a085d1f2e 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -41,10 +41,10 @@ | |||
41 | #include "v9fs_vfs.h" | 41 | #include "v9fs_vfs.h" |
42 | #include "fid.h" | 42 | #include "fid.h" |
43 | 43 | ||
44 | static struct inode_operations v9fs_dir_inode_operations; | 44 | static const struct inode_operations v9fs_dir_inode_operations; |
45 | static struct inode_operations v9fs_dir_inode_operations_ext; | 45 | static const struct inode_operations v9fs_dir_inode_operations_ext; |
46 | static struct inode_operations v9fs_file_inode_operations; | 46 | static const struct inode_operations v9fs_file_inode_operations; |
47 | static struct inode_operations v9fs_symlink_inode_operations; | 47 | static const struct inode_operations v9fs_symlink_inode_operations; |
48 | 48 | ||
49 | /** | 49 | /** |
50 | * unixmode2p9mode - convert unix mode bits to plan 9 | 50 | * unixmode2p9mode - convert unix mode bits to plan 9 |
@@ -504,7 +504,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
504 | goto error; | 504 | goto error; |
505 | } | 505 | } |
506 | 506 | ||
507 | dentry->d_op = &v9fs_dentry_operations; | 507 | if(v9ses->cache) |
508 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
509 | else | ||
510 | dentry->d_op = &v9fs_dentry_operations; | ||
508 | d_instantiate(dentry, inode); | 511 | d_instantiate(dentry, inode); |
509 | 512 | ||
510 | if (nd && nd->flags & LOOKUP_OPEN) { | 513 | if (nd && nd->flags & LOOKUP_OPEN) { |
@@ -585,17 +588,17 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
585 | if (IS_ERR(inode)) { | 588 | if (IS_ERR(inode)) { |
586 | err = PTR_ERR(inode); | 589 | err = PTR_ERR(inode); |
587 | inode = NULL; | 590 | inode = NULL; |
588 | goto clean_up_fids; | 591 | v9fs_fid_destroy(vfid); |
592 | goto error; | ||
589 | } | 593 | } |
590 | 594 | ||
591 | dentry->d_op = &v9fs_dentry_operations; | 595 | if(v9ses->cache) |
596 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
597 | else | ||
598 | dentry->d_op = &v9fs_dentry_operations; | ||
592 | d_instantiate(dentry, inode); | 599 | d_instantiate(dentry, inode); |
593 | return 0; | 600 | return 0; |
594 | 601 | ||
595 | clean_up_fids: | ||
596 | if (vfid) | ||
597 | v9fs_fid_destroy(vfid); | ||
598 | |||
599 | clean_up_dfid: | 602 | clean_up_dfid: |
600 | v9fs_fid_clunk(v9ses, dfid); | 603 | v9fs_fid_clunk(v9ses, dfid); |
601 | 604 | ||
@@ -629,7 +632,6 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
629 | 632 | ||
630 | sb = dir->i_sb; | 633 | sb = dir->i_sb; |
631 | v9ses = v9fs_inode2v9ses(dir); | 634 | v9ses = v9fs_inode2v9ses(dir); |
632 | dentry->d_op = &v9fs_dentry_operations; | ||
633 | dirfid = v9fs_fid_lookup(dentry->d_parent); | 635 | dirfid = v9fs_fid_lookup(dentry->d_parent); |
634 | 636 | ||
635 | if(IS_ERR(dirfid)) | 637 | if(IS_ERR(dirfid)) |
@@ -700,6 +702,10 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
700 | 702 | ||
701 | fid->qid = fcall->params.rstat.stat.qid; | 703 | fid->qid = fcall->params.rstat.stat.qid; |
702 | v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb); | 704 | v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb); |
705 | if((fid->qid.version)&&(v9ses->cache)) | ||
706 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
707 | else | ||
708 | dentry->d_op = &v9fs_dentry_operations; | ||
703 | 709 | ||
704 | d_add(dentry, inode); | 710 | d_add(dentry, inode); |
705 | kfree(fcall); | 711 | kfree(fcall); |
@@ -1187,7 +1193,10 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, | |||
1187 | goto free_vfid; | 1193 | goto free_vfid; |
1188 | } | 1194 | } |
1189 | 1195 | ||
1190 | dentry->d_op = &v9fs_dentry_operations; | 1196 | if(v9ses->cache) |
1197 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
1198 | else | ||
1199 | dentry->d_op = &v9fs_dentry_operations; | ||
1191 | d_instantiate(dentry, inode); | 1200 | d_instantiate(dentry, inode); |
1192 | return 0; | 1201 | return 0; |
1193 | 1202 | ||
@@ -1306,7 +1315,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1306 | return retval; | 1315 | return retval; |
1307 | } | 1316 | } |
1308 | 1317 | ||
1309 | static struct inode_operations v9fs_dir_inode_operations_ext = { | 1318 | static const struct inode_operations v9fs_dir_inode_operations_ext = { |
1310 | .create = v9fs_vfs_create, | 1319 | .create = v9fs_vfs_create, |
1311 | .lookup = v9fs_vfs_lookup, | 1320 | .lookup = v9fs_vfs_lookup, |
1312 | .symlink = v9fs_vfs_symlink, | 1321 | .symlink = v9fs_vfs_symlink, |
@@ -1321,7 +1330,7 @@ static struct inode_operations v9fs_dir_inode_operations_ext = { | |||
1321 | .setattr = v9fs_vfs_setattr, | 1330 | .setattr = v9fs_vfs_setattr, |
1322 | }; | 1331 | }; |
1323 | 1332 | ||
1324 | static struct inode_operations v9fs_dir_inode_operations = { | 1333 | static const struct inode_operations v9fs_dir_inode_operations = { |
1325 | .create = v9fs_vfs_create, | 1334 | .create = v9fs_vfs_create, |
1326 | .lookup = v9fs_vfs_lookup, | 1335 | .lookup = v9fs_vfs_lookup, |
1327 | .unlink = v9fs_vfs_unlink, | 1336 | .unlink = v9fs_vfs_unlink, |
@@ -1333,12 +1342,12 @@ static struct inode_operations v9fs_dir_inode_operations = { | |||
1333 | .setattr = v9fs_vfs_setattr, | 1342 | .setattr = v9fs_vfs_setattr, |
1334 | }; | 1343 | }; |
1335 | 1344 | ||
1336 | static struct inode_operations v9fs_file_inode_operations = { | 1345 | static const struct inode_operations v9fs_file_inode_operations = { |
1337 | .getattr = v9fs_vfs_getattr, | 1346 | .getattr = v9fs_vfs_getattr, |
1338 | .setattr = v9fs_vfs_setattr, | 1347 | .setattr = v9fs_vfs_setattr, |
1339 | }; | 1348 | }; |
1340 | 1349 | ||
1341 | static struct inode_operations v9fs_symlink_inode_operations = { | 1350 | static const struct inode_operations v9fs_symlink_inode_operations = { |
1342 | .readlink = v9fs_vfs_readlink, | 1351 | .readlink = v9fs_vfs_readlink, |
1343 | .follow_link = v9fs_vfs_follow_link, | 1352 | .follow_link = v9fs_vfs_follow_link, |
1344 | .put_link = v9fs_vfs_put_link, | 1353 | .put_link = v9fs_vfs_put_link, |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 63320d4e15d2..0ec42f665457 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include "fid.h" | 45 | #include "fid.h" |
46 | 46 | ||
47 | static void v9fs_clear_inode(struct inode *); | 47 | static void v9fs_clear_inode(struct inode *); |
48 | static struct super_operations v9fs_super_ops; | 48 | static const struct super_operations v9fs_super_ops; |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * v9fs_clear_inode - release an inode | 51 | * v9fs_clear_inode - release an inode |
@@ -263,7 +263,7 @@ v9fs_umount_begin(struct vfsmount *vfsmnt, int flags) | |||
263 | v9fs_session_cancel(v9ses); | 263 | v9fs_session_cancel(v9ses); |
264 | } | 264 | } |
265 | 265 | ||
266 | static struct super_operations v9fs_super_ops = { | 266 | static const struct super_operations v9fs_super_ops = { |
267 | .statfs = simple_statfs, | 267 | .statfs = simple_statfs, |
268 | .clear_inode = v9fs_clear_inode, | 268 | .clear_inode = v9fs_clear_inode, |
269 | .show_options = v9fs_show_options, | 269 | .show_options = v9fs_show_options, |
diff --git a/fs/Kconfig b/fs/Kconfig index 5e8e9d9ccb33..3c4886b849f5 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -674,12 +674,6 @@ config ZISOFS | |||
674 | necessary to create such a filesystem. Say Y here if you want to be | 674 | necessary to create such a filesystem. Say Y here if you want to be |
675 | able to read such compressed CD-ROMs. | 675 | able to read such compressed CD-ROMs. |
676 | 676 | ||
677 | config ZISOFS_FS | ||
678 | # for fs/nls/Config.in | ||
679 | tristate | ||
680 | depends on ZISOFS | ||
681 | default ISO9660_FS | ||
682 | |||
683 | config UDF_FS | 677 | config UDF_FS |
684 | tristate "UDF file system support" | 678 | tristate "UDF file system support" |
685 | help | 679 | help |
@@ -1094,7 +1088,7 @@ config AFFS_FS | |||
1094 | 1088 | ||
1095 | config ECRYPT_FS | 1089 | config ECRYPT_FS |
1096 | tristate "eCrypt filesystem layer support (EXPERIMENTAL)" | 1090 | tristate "eCrypt filesystem layer support (EXPERIMENTAL)" |
1097 | depends on EXPERIMENTAL && KEYS && CRYPTO | 1091 | depends on EXPERIMENTAL && KEYS && CRYPTO && NET |
1098 | help | 1092 | help |
1099 | Encrypted filesystem that operates on the VFS layer. See | 1093 | Encrypted filesystem that operates on the VFS layer. See |
1100 | <file:Documentation/ecryptfs.txt> to learn more about | 1094 | <file:Documentation/ecryptfs.txt> to learn more about |
@@ -1195,32 +1189,6 @@ config EFS_FS | |||
1195 | To compile the EFS file system support as a module, choose M here: the | 1189 | To compile the EFS file system support as a module, choose M here: the |
1196 | module will be called efs. | 1190 | module will be called efs. |
1197 | 1191 | ||
1198 | config JFFS_FS | ||
1199 | tristate "Journalling Flash File System (JFFS) support" | ||
1200 | depends on MTD && BLOCK && BROKEN | ||
1201 | help | ||
1202 | JFFS is the Journalling Flash File System developed by Axis | ||
1203 | Communications in Sweden, aimed at providing a crash/powerdown-safe | ||
1204 | file system for disk-less embedded devices. Further information is | ||
1205 | available at (<http://developer.axis.com/software/jffs/>). | ||
1206 | |||
1207 | NOTE: This filesystem is deprecated and is scheduled for removal in | ||
1208 | 2.6.21. See Documentation/feature-removal-schedule.txt | ||
1209 | |||
1210 | config JFFS_FS_VERBOSE | ||
1211 | int "JFFS debugging verbosity (0 = quiet, 3 = noisy)" | ||
1212 | depends on JFFS_FS | ||
1213 | default "0" | ||
1214 | help | ||
1215 | Determines the verbosity level of the JFFS debugging messages. | ||
1216 | |||
1217 | config JFFS_PROC_FS | ||
1218 | bool "JFFS stats available in /proc filesystem" | ||
1219 | depends on JFFS_FS && PROC_FS | ||
1220 | help | ||
1221 | Enabling this option will cause statistics from mounted JFFS file systems | ||
1222 | to be made available to the user in the /proc/fs/jffs/ directory. | ||
1223 | |||
1224 | config JFFS2_FS | 1192 | config JFFS2_FS |
1225 | tristate "Journalling Flash File System v2 (JFFS2) support" | 1193 | tristate "Journalling Flash File System v2 (JFFS2) support" |
1226 | select CRC32 | 1194 | select CRC32 |
@@ -1870,20 +1838,14 @@ config CIFS | |||
1870 | file servers such as Windows 2000 (including Windows 2003, NT 4 | 1838 | file servers such as Windows 2000 (including Windows 2003, NT 4 |
1871 | and Windows XP) as well by Samba (which provides excellent CIFS | 1839 | and Windows XP) as well by Samba (which provides excellent CIFS |
1872 | server support for Linux and many other operating systems). Limited | 1840 | server support for Linux and many other operating systems). Limited |
1873 | support for Windows ME and similar servers is provided as well. | 1841 | support for OS/2 and Windows ME and similar servers is provided as well. |
1874 | You must use the smbfs client filesystem to access older SMB servers | ||
1875 | such as OS/2 and DOS. | ||
1876 | 1842 | ||
1877 | The intent of the cifs module is to provide an advanced | 1843 | The intent of the cifs module is to provide an advanced |
1878 | network file system client for mounting to CIFS compliant servers, | 1844 | network file system client for mounting to CIFS compliant servers, |
1879 | including support for dfs (hierarchical name space), secure per-user | 1845 | including support for dfs (hierarchical name space), secure per-user |
1880 | session establishment, safe distributed caching (oplock), optional | 1846 | session establishment, safe distributed caching (oplock), optional |
1881 | packet signing, Unicode and other internationalization improvements, | 1847 | packet signing, Unicode and other internationalization improvements. |
1882 | and optional Winbind (nsswitch) integration. You do not need to enable | 1848 | If you need to mount to Samba or Windows from this machine, say Y. |
1883 | cifs if running only a (Samba) server. It is possible to enable both | ||
1884 | smbfs and cifs (e.g. if you are using CIFS for accessing Windows 2003 | ||
1885 | and Samba 3 servers, and smbfs for accessing old servers). If you need | ||
1886 | to mount to Samba or Windows from this machine, say Y. | ||
1887 | 1849 | ||
1888 | config CIFS_STATS | 1850 | config CIFS_STATS |
1889 | bool "CIFS statistics" | 1851 | bool "CIFS statistics" |
@@ -1976,14 +1938,13 @@ config CIFS_EXPERIMENTAL | |||
1976 | depends on CIFS && EXPERIMENTAL | 1938 | depends on CIFS && EXPERIMENTAL |
1977 | help | 1939 | help |
1978 | Enables cifs features under testing. These features are | 1940 | Enables cifs features under testing. These features are |
1979 | experimental and currently include support for writepages | 1941 | experimental and currently include DFS support and directory |
1980 | (multipage writebehind performance improvements) and directory | 1942 | change notification ie fcntl(F_DNOTIFY), as well as the upcall |
1981 | change notification ie fcntl(F_DNOTIFY) as well as some security | 1943 | mechanism which will be used for Kerberos session negotiation |
1982 | improvements. Some also depend on setting at runtime the | 1944 | and uid remapping. Some of these features also may depend on |
1983 | pseudo-file /proc/fs/cifs/Experimental (which is disabled by | 1945 | setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental |
1984 | default). See the file fs/cifs/README for more details. | 1946 | (which is disabled by default). See the file fs/cifs/README |
1985 | 1947 | for more details. If unsure, say N. | |
1986 | If unsure, say N. | ||
1987 | 1948 | ||
1988 | config CIFS_UPCALL | 1949 | config CIFS_UPCALL |
1989 | bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" | 1950 | bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" |
diff --git a/fs/Makefile b/fs/Makefile index b9ffa63f77fc..9edf4112bee0 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -94,7 +94,6 @@ obj-$(CONFIG_HPFS_FS) += hpfs/ | |||
94 | obj-$(CONFIG_NTFS_FS) += ntfs/ | 94 | obj-$(CONFIG_NTFS_FS) += ntfs/ |
95 | obj-$(CONFIG_UFS_FS) += ufs/ | 95 | obj-$(CONFIG_UFS_FS) += ufs/ |
96 | obj-$(CONFIG_EFS_FS) += efs/ | 96 | obj-$(CONFIG_EFS_FS) += efs/ |
97 | obj-$(CONFIG_JFFS_FS) += jffs/ | ||
98 | obj-$(CONFIG_JFFS2_FS) += jffs2/ | 97 | obj-$(CONFIG_JFFS2_FS) += jffs2/ |
99 | obj-$(CONFIG_AFFS_FS) += affs/ | 98 | obj-$(CONFIG_AFFS_FS) += affs/ |
100 | obj-$(CONFIG_ROMFS_FS) += romfs/ | 99 | obj-$(CONFIG_ROMFS_FS) += romfs/ |
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index 29217ff36d44..936f2af39c43 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h | |||
@@ -84,7 +84,7 @@ void __adfs_error(struct super_block *sb, const char *function, | |||
84 | */ | 84 | */ |
85 | 85 | ||
86 | /* dir_*.c */ | 86 | /* dir_*.c */ |
87 | extern struct inode_operations adfs_dir_inode_operations; | 87 | extern const struct inode_operations adfs_dir_inode_operations; |
88 | extern const struct file_operations adfs_dir_operations; | 88 | extern const struct file_operations adfs_dir_operations; |
89 | extern struct dentry_operations adfs_dentry_operations; | 89 | extern struct dentry_operations adfs_dentry_operations; |
90 | extern struct adfs_dir_ops adfs_f_dir_ops; | 90 | extern struct adfs_dir_ops adfs_f_dir_ops; |
@@ -93,7 +93,7 @@ extern struct adfs_dir_ops adfs_fplus_dir_ops; | |||
93 | extern int adfs_dir_update(struct super_block *sb, struct object_info *obj); | 93 | extern int adfs_dir_update(struct super_block *sb, struct object_info *obj); |
94 | 94 | ||
95 | /* file.c */ | 95 | /* file.c */ |
96 | extern struct inode_operations adfs_file_inode_operations; | 96 | extern const struct inode_operations adfs_file_inode_operations; |
97 | extern const struct file_operations adfs_file_operations; | 97 | extern const struct file_operations adfs_file_operations; |
98 | 98 | ||
99 | static inline __u32 signed_asl(__u32 val, signed int shift) | 99 | static inline __u32 signed_asl(__u32 val, signed int shift) |
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 2b8903893d3f..fc1a8dc64d78 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c | |||
@@ -295,7 +295,7 @@ adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
295 | /* | 295 | /* |
296 | * directories can handle most operations... | 296 | * directories can handle most operations... |
297 | */ | 297 | */ |
298 | struct inode_operations adfs_dir_inode_operations = { | 298 | const struct inode_operations adfs_dir_inode_operations = { |
299 | .lookup = adfs_lookup, | 299 | .lookup = adfs_lookup, |
300 | .setattr = adfs_notify_change, | 300 | .setattr = adfs_notify_change, |
301 | }; | 301 | }; |
diff --git a/fs/adfs/file.c b/fs/adfs/file.c index 6101ea679cb1..f544a2855923 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c | |||
@@ -36,6 +36,6 @@ const struct file_operations adfs_file_operations = { | |||
36 | .sendfile = generic_file_sendfile, | 36 | .sendfile = generic_file_sendfile, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct inode_operations adfs_file_inode_operations = { | 39 | const struct inode_operations adfs_file_inode_operations = { |
40 | .setattr = adfs_notify_change, | 40 | .setattr = adfs_notify_change, |
41 | }; | 41 | }; |
diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 5023351a7afe..2e5f2c8371ee 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c | |||
@@ -254,7 +254,7 @@ static void destroy_inodecache(void) | |||
254 | kmem_cache_destroy(adfs_inode_cachep); | 254 | kmem_cache_destroy(adfs_inode_cachep); |
255 | } | 255 | } |
256 | 256 | ||
257 | static struct super_operations adfs_sops = { | 257 | static const struct super_operations adfs_sops = { |
258 | .alloc_inode = adfs_alloc_inode, | 258 | .alloc_inode = adfs_alloc_inode, |
259 | .destroy_inode = adfs_destroy_inode, | 259 | .destroy_inode = adfs_destroy_inode, |
260 | .write_inode = adfs_write_inode, | 260 | .write_inode = adfs_write_inode, |
diff --git a/fs/affs/affs.h b/fs/affs/affs.h index 1dc8438ef389..232c69493683 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h | |||
@@ -171,6 +171,7 @@ extern unsigned long affs_parent_ino(struct inode *dir); | |||
171 | extern struct inode *affs_new_inode(struct inode *dir); | 171 | extern struct inode *affs_new_inode(struct inode *dir); |
172 | extern int affs_notify_change(struct dentry *dentry, struct iattr *attr); | 172 | extern int affs_notify_change(struct dentry *dentry, struct iattr *attr); |
173 | extern void affs_put_inode(struct inode *inode); | 173 | extern void affs_put_inode(struct inode *inode); |
174 | extern void affs_drop_inode(struct inode *inode); | ||
174 | extern void affs_delete_inode(struct inode *inode); | 175 | extern void affs_delete_inode(struct inode *inode); |
175 | extern void affs_clear_inode(struct inode *inode); | 176 | extern void affs_clear_inode(struct inode *inode); |
176 | extern void affs_read_inode(struct inode *inode); | 177 | extern void affs_read_inode(struct inode *inode); |
@@ -188,9 +189,9 @@ extern void affs_dir_truncate(struct inode *); | |||
188 | 189 | ||
189 | /* jump tables */ | 190 | /* jump tables */ |
190 | 191 | ||
191 | extern struct inode_operations affs_file_inode_operations; | 192 | extern const struct inode_operations affs_file_inode_operations; |
192 | extern struct inode_operations affs_dir_inode_operations; | 193 | extern const struct inode_operations affs_dir_inode_operations; |
193 | extern struct inode_operations affs_symlink_inode_operations; | 194 | extern const struct inode_operations affs_symlink_inode_operations; |
194 | extern const struct file_operations affs_file_operations; | 195 | extern const struct file_operations affs_file_operations; |
195 | extern const struct file_operations affs_file_operations_ofs; | 196 | extern const struct file_operations affs_file_operations_ofs; |
196 | extern const struct file_operations affs_dir_operations; | 197 | extern const struct file_operations affs_dir_operations; |
diff --git a/fs/affs/dir.c b/fs/affs/dir.c index cad3ee340063..6e3f282424b0 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c | |||
@@ -26,7 +26,7 @@ const struct file_operations affs_dir_operations = { | |||
26 | /* | 26 | /* |
27 | * directories can handle most operations... | 27 | * directories can handle most operations... |
28 | */ | 28 | */ |
29 | struct inode_operations affs_dir_inode_operations = { | 29 | const struct inode_operations affs_dir_inode_operations = { |
30 | .create = affs_create, | 30 | .create = affs_create, |
31 | .lookup = affs_lookup, | 31 | .lookup = affs_lookup, |
32 | .link = affs_link, | 32 | .link = affs_link, |
diff --git a/fs/affs/file.c b/fs/affs/file.c index 05b5e22de759..4aa8079e71be 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
@@ -38,7 +38,7 @@ const struct file_operations affs_file_operations = { | |||
38 | .sendfile = generic_file_sendfile, | 38 | .sendfile = generic_file_sendfile, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | struct inode_operations affs_file_inode_operations = { | 41 | const struct inode_operations affs_file_inode_operations = { |
42 | .truncate = affs_truncate, | 42 | .truncate = affs_truncate, |
43 | .setattr = affs_notify_change, | 43 | .setattr = affs_notify_change, |
44 | }; | 44 | }; |
diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 44d439cb69f4..c5b9d73c084a 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | #include "affs.h" | 13 | #include "affs.h" |
14 | 14 | ||
15 | extern struct inode_operations affs_symlink_inode_operations; | 15 | extern const struct inode_operations affs_symlink_inode_operations; |
16 | extern struct timezone sys_tz; | 16 | extern struct timezone sys_tz; |
17 | 17 | ||
18 | void | 18 | void |
@@ -243,12 +243,17 @@ affs_put_inode(struct inode *inode) | |||
243 | { | 243 | { |
244 | pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); | 244 | pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); |
245 | affs_free_prealloc(inode); | 245 | affs_free_prealloc(inode); |
246 | if (atomic_read(&inode->i_count) == 1) { | 246 | } |
247 | mutex_lock(&inode->i_mutex); | 247 | |
248 | if (inode->i_size != AFFS_I(inode)->mmu_private) | 248 | void |
249 | affs_truncate(inode); | 249 | affs_drop_inode(struct inode *inode) |
250 | mutex_unlock(&inode->i_mutex); | 250 | { |
251 | } | 251 | mutex_lock(&inode->i_mutex); |
252 | if (inode->i_size != AFFS_I(inode)->mmu_private) | ||
253 | affs_truncate(inode); | ||
254 | mutex_unlock(&inode->i_mutex); | ||
255 | |||
256 | generic_drop_inode(inode); | ||
252 | } | 257 | } |
253 | 258 | ||
254 | void | 259 | void |
diff --git a/fs/affs/super.c b/fs/affs/super.c index 3de93e799949..c3986a1911b0 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
@@ -112,12 +112,13 @@ static void destroy_inodecache(void) | |||
112 | kmem_cache_destroy(affs_inode_cachep); | 112 | kmem_cache_destroy(affs_inode_cachep); |
113 | } | 113 | } |
114 | 114 | ||
115 | static struct super_operations affs_sops = { | 115 | static const struct super_operations affs_sops = { |
116 | .alloc_inode = affs_alloc_inode, | 116 | .alloc_inode = affs_alloc_inode, |
117 | .destroy_inode = affs_destroy_inode, | 117 | .destroy_inode = affs_destroy_inode, |
118 | .read_inode = affs_read_inode, | 118 | .read_inode = affs_read_inode, |
119 | .write_inode = affs_write_inode, | 119 | .write_inode = affs_write_inode, |
120 | .put_inode = affs_put_inode, | 120 | .put_inode = affs_put_inode, |
121 | .drop_inode = affs_drop_inode, | ||
121 | .delete_inode = affs_delete_inode, | 122 | .delete_inode = affs_delete_inode, |
122 | .clear_inode = affs_clear_inode, | 123 | .clear_inode = affs_clear_inode, |
123 | .put_super = affs_put_super, | 124 | .put_super = affs_put_super, |
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index f802256a5933..41782539c907 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c | |||
@@ -70,7 +70,7 @@ const struct address_space_operations affs_symlink_aops = { | |||
70 | .readpage = affs_symlink_readpage, | 70 | .readpage = affs_symlink_readpage, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | struct inode_operations affs_symlink_inode_operations = { | 73 | const struct inode_operations affs_symlink_inode_operations = { |
74 | .readlink = generic_readlink, | 74 | .readlink = generic_readlink, |
75 | .follow_link = page_follow_link_light, | 75 | .follow_link = page_follow_link_light, |
76 | .put_link = page_put_link, | 76 | .put_link = page_put_link, |
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index bfc1fd22d5b1..1fc578372759 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -10,7 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/sched.h> | ||
14 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
15 | #include <rxrpc/peer.h> | 14 | #include <rxrpc/peer.h> |
16 | #include <rxrpc/connection.h> | 15 | #include <rxrpc/connection.h> |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 4acd04134055..b6dc2ebe47a8 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/sched.h> | ||
16 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
17 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
18 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
@@ -37,7 +36,7 @@ const struct file_operations afs_dir_file_operations = { | |||
37 | .readdir = afs_dir_readdir, | 36 | .readdir = afs_dir_readdir, |
38 | }; | 37 | }; |
39 | 38 | ||
40 | struct inode_operations afs_dir_inode_operations = { | 39 | const struct inode_operations afs_dir_inode_operations = { |
41 | .lookup = afs_dir_lookup, | 40 | .lookup = afs_dir_lookup, |
42 | .getattr = afs_inode_getattr, | 41 | .getattr = afs_inode_getattr, |
43 | #if 0 /* TODO */ | 42 | #if 0 /* TODO */ |
diff --git a/fs/afs/file.c b/fs/afs/file.c index 2e8c42639eaa..b17634541f67 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/sched.h> | ||
16 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
17 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
18 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
@@ -30,7 +29,7 @@ static int afs_file_readpage(struct file *file, struct page *page); | |||
30 | static void afs_file_invalidatepage(struct page *page, unsigned long offset); | 29 | static void afs_file_invalidatepage(struct page *page, unsigned long offset); |
31 | static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); | 30 | static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); |
32 | 31 | ||
33 | struct inode_operations afs_file_inode_operations = { | 32 | const struct inode_operations afs_file_inode_operations = { |
34 | .getattr = afs_inode_getattr, | 33 | .getattr = afs_inode_getattr, |
35 | }; | 34 | }; |
36 | 35 | ||
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 6f37754906c2..9d9bca6c28b5 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/sched.h> | ||
20 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
21 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
22 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index e88b3b65ae49..5151d5da2c2f 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -63,14 +63,14 @@ extern struct cachefs_index_def afs_cache_cell_index_def; | |||
63 | /* | 63 | /* |
64 | * dir.c | 64 | * dir.c |
65 | */ | 65 | */ |
66 | extern struct inode_operations afs_dir_inode_operations; | 66 | extern const struct inode_operations afs_dir_inode_operations; |
67 | extern const struct file_operations afs_dir_file_operations; | 67 | extern const struct file_operations afs_dir_file_operations; |
68 | 68 | ||
69 | /* | 69 | /* |
70 | * file.c | 70 | * file.c |
71 | */ | 71 | */ |
72 | extern const struct address_space_operations afs_fs_aops; | 72 | extern const struct address_space_operations afs_fs_aops; |
73 | extern struct inode_operations afs_file_inode_operations; | 73 | extern const struct inode_operations afs_file_inode_operations; |
74 | 74 | ||
75 | #ifdef AFS_CACHING_SUPPORT | 75 | #ifdef AFS_CACHING_SUPPORT |
76 | extern int afs_cache_get_page_cookie(struct page *page, | 76 | extern int afs_cache_get_page_cookie(struct page *page, |
@@ -104,7 +104,7 @@ extern struct cachefs_netfs afs_cache_netfs; | |||
104 | /* | 104 | /* |
105 | * mntpt.c | 105 | * mntpt.c |
106 | */ | 106 | */ |
107 | extern struct inode_operations afs_mntpt_inode_operations; | 107 | extern const struct inode_operations afs_mntpt_inode_operations; |
108 | extern const struct file_operations afs_mntpt_file_operations; | 108 | extern const struct file_operations afs_mntpt_file_operations; |
109 | extern struct afs_timer afs_mntpt_expiry_timer; | 109 | extern struct afs_timer afs_mntpt_expiry_timer; |
110 | extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; | 110 | extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; |
diff --git a/fs/afs/main.c b/fs/afs/main.c index 913c689bdb35..f2704ba53857 100644 --- a/fs/afs/main.c +++ b/fs/afs/main.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/moduleparam.h> | 13 | #include <linux/moduleparam.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/sched.h> | ||
16 | #include <linux/completion.h> | 15 | #include <linux/completion.h> |
17 | #include <rxrpc/rxrpc.h> | 16 | #include <rxrpc/rxrpc.h> |
18 | #include <rxrpc/transport.h> | 17 | #include <rxrpc/transport.h> |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 8f74e8450826..68495f0de7b3 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/sched.h> | ||
16 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
17 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
18 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
@@ -36,7 +35,7 @@ const struct file_operations afs_mntpt_file_operations = { | |||
36 | .open = afs_mntpt_open, | 35 | .open = afs_mntpt_open, |
37 | }; | 36 | }; |
38 | 37 | ||
39 | struct inode_operations afs_mntpt_inode_operations = { | 38 | const struct inode_operations afs_mntpt_inode_operations = { |
40 | .lookup = afs_mntpt_lookup, | 39 | .lookup = afs_mntpt_lookup, |
41 | .follow_link = afs_mntpt_follow_link, | 40 | .follow_link = afs_mntpt_follow_link, |
42 | .readlink = page_readlink, | 41 | .readlink = page_readlink, |
diff --git a/fs/afs/proc.c b/fs/afs/proc.c index 86463ec9ccb4..ae6b85b1e484 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c | |||
@@ -9,7 +9,6 @@ | |||
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
15 | #include <linux/proc_fs.h> | 14 | #include <linux/proc_fs.h> |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 18d9b77ba40f..eb7e32349da3 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -56,7 +56,7 @@ struct file_system_type afs_fs_type = { | |||
56 | .fs_flags = FS_BINARY_MOUNTDATA, | 56 | .fs_flags = FS_BINARY_MOUNTDATA, |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static struct super_operations afs_super_ops = { | 59 | static const struct super_operations afs_super_ops = { |
60 | .statfs = simple_statfs, | 60 | .statfs = simple_statfs, |
61 | .alloc_inode = afs_alloc_inode, | 61 | .alloc_inode = afs_alloc_inode, |
62 | .drop_inode = generic_delete_inode, | 62 | .drop_inode = generic_delete_inode, |
@@ -132,7 +132,7 @@ static int aio_setup_ring(struct kioctx *ctx) | |||
132 | dprintk("attempting mmap of %lu bytes\n", info->mmap_size); | 132 | dprintk("attempting mmap of %lu bytes\n", info->mmap_size); |
133 | down_write(&ctx->mm->mmap_sem); | 133 | down_write(&ctx->mm->mmap_sem); |
134 | info->mmap_base = do_mmap(NULL, 0, info->mmap_size, | 134 | info->mmap_base = do_mmap(NULL, 0, info->mmap_size, |
135 | PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, | 135 | PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, |
136 | 0); | 136 | 0); |
137 | if (IS_ERR((void *)info->mmap_base)) { | 137 | if (IS_ERR((void *)info->mmap_base)) { |
138 | up_write(&ctx->mm->mmap_sem); | 138 | up_write(&ctx->mm->mmap_sem); |
@@ -211,11 +211,10 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) | |||
211 | if ((unsigned long)nr_events > aio_max_nr) | 211 | if ((unsigned long)nr_events > aio_max_nr) |
212 | return ERR_PTR(-EAGAIN); | 212 | return ERR_PTR(-EAGAIN); |
213 | 213 | ||
214 | ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL); | 214 | ctx = kmem_cache_zalloc(kioctx_cachep, GFP_KERNEL); |
215 | if (!ctx) | 215 | if (!ctx) |
216 | return ERR_PTR(-ENOMEM); | 216 | return ERR_PTR(-ENOMEM); |
217 | 217 | ||
218 | memset(ctx, 0, sizeof(*ctx)); | ||
219 | ctx->max_reqs = nr_events; | 218 | ctx->max_reqs = nr_events; |
220 | mm = ctx->mm = current->mm; | 219 | mm = ctx->mm = current->mm; |
221 | atomic_inc(&mm->mm_count); | 220 | atomic_inc(&mm->mm_count); |
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 906ba5ce2261..4ef544434b51 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h | |||
@@ -142,8 +142,8 @@ struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info | |||
142 | 142 | ||
143 | /* Operations structures */ | 143 | /* Operations structures */ |
144 | 144 | ||
145 | extern struct inode_operations autofs_root_inode_operations; | 145 | extern const struct inode_operations autofs_root_inode_operations; |
146 | extern struct inode_operations autofs_symlink_inode_operations; | 146 | extern const struct inode_operations autofs_symlink_inode_operations; |
147 | extern const struct file_operations autofs_root_operations; | 147 | extern const struct file_operations autofs_root_operations; |
148 | 148 | ||
149 | /* Initializing function */ | 149 | /* Initializing function */ |
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index f968d1342808..aa0b61ff8270 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c | |||
@@ -52,7 +52,7 @@ out_kill_sb: | |||
52 | 52 | ||
53 | static void autofs_read_inode(struct inode *inode); | 53 | static void autofs_read_inode(struct inode *inode); |
54 | 54 | ||
55 | static struct super_operations autofs_sops = { | 55 | static const struct super_operations autofs_sops = { |
56 | .read_inode = autofs_read_inode, | 56 | .read_inode = autofs_read_inode, |
57 | .statfs = simple_statfs, | 57 | .statfs = simple_statfs, |
58 | }; | 58 | }; |
diff --git a/fs/autofs/root.c b/fs/autofs/root.c index e698c51d2b02..f2597205939d 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c | |||
@@ -32,7 +32,7 @@ const struct file_operations autofs_root_operations = { | |||
32 | .ioctl = autofs_root_ioctl, | 32 | .ioctl = autofs_root_ioctl, |
33 | }; | 33 | }; |
34 | 34 | ||
35 | struct inode_operations autofs_root_inode_operations = { | 35 | const struct inode_operations autofs_root_inode_operations = { |
36 | .lookup = autofs_root_lookup, | 36 | .lookup = autofs_root_lookup, |
37 | .unlink = autofs_root_unlink, | 37 | .unlink = autofs_root_unlink, |
38 | .symlink = autofs_root_symlink, | 38 | .symlink = autofs_root_symlink, |
diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c index c74f2eb65775..7ce9cb2c9ce2 100644 --- a/fs/autofs/symlink.c +++ b/fs/autofs/symlink.c | |||
@@ -20,7 +20,7 @@ static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
20 | return NULL; | 20 | return NULL; |
21 | } | 21 | } |
22 | 22 | ||
23 | struct inode_operations autofs_symlink_inode_operations = { | 23 | const struct inode_operations autofs_symlink_inode_operations = { |
24 | .readlink = generic_readlink, | 24 | .readlink = generic_readlink, |
25 | .follow_link = autofs_follow_link | 25 | .follow_link = autofs_follow_link |
26 | }; | 26 | }; |
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 216b1a364ccb..d85f42fa9206 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -52,6 +52,8 @@ struct autofs_info { | |||
52 | 52 | ||
53 | int flags; | 53 | int flags; |
54 | 54 | ||
55 | struct list_head rehash; | ||
56 | |||
55 | struct autofs_sb_info *sbi; | 57 | struct autofs_sb_info *sbi; |
56 | unsigned long last_used; | 58 | unsigned long last_used; |
57 | atomic_t count; | 59 | atomic_t count; |
@@ -110,6 +112,8 @@ struct autofs_sb_info { | |||
110 | struct mutex wq_mutex; | 112 | struct mutex wq_mutex; |
111 | spinlock_t fs_lock; | 113 | spinlock_t fs_lock; |
112 | struct autofs_wait_queue *queues; /* Wait queue pointer */ | 114 | struct autofs_wait_queue *queues; /* Wait queue pointer */ |
115 | spinlock_t rehash_lock; | ||
116 | struct list_head rehash_list; | ||
113 | }; | 117 | }; |
114 | 118 | ||
115 | static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb) | 119 | static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb) |
@@ -168,11 +172,11 @@ int autofs4_expire_multi(struct super_block *, struct vfsmount *, | |||
168 | 172 | ||
169 | /* Operations structures */ | 173 | /* Operations structures */ |
170 | 174 | ||
171 | extern struct inode_operations autofs4_symlink_inode_operations; | 175 | extern const struct inode_operations autofs4_symlink_inode_operations; |
172 | extern struct inode_operations autofs4_dir_inode_operations; | 176 | extern const struct inode_operations autofs4_dir_inode_operations; |
173 | extern struct inode_operations autofs4_root_inode_operations; | 177 | extern const struct inode_operations autofs4_root_inode_operations; |
174 | extern struct inode_operations autofs4_indirect_root_inode_operations; | 178 | extern const struct inode_operations autofs4_indirect_root_inode_operations; |
175 | extern struct inode_operations autofs4_direct_root_inode_operations; | 179 | extern const struct inode_operations autofs4_direct_root_inode_operations; |
176 | extern const struct file_operations autofs4_dir_operations; | 180 | extern const struct file_operations autofs4_dir_operations; |
177 | extern const struct file_operations autofs4_root_operations; | 181 | extern const struct file_operations autofs4_root_operations; |
178 | 182 | ||
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index e8f6c5ad3e90..26063dc84a2a 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -48,6 +48,8 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, | |||
48 | ino->dentry = NULL; | 48 | ino->dentry = NULL; |
49 | ino->size = 0; | 49 | ino->size = 0; |
50 | 50 | ||
51 | INIT_LIST_HEAD(&ino->rehash); | ||
52 | |||
51 | ino->last_used = jiffies; | 53 | ino->last_used = jiffies; |
52 | atomic_set(&ino->count, 0); | 54 | atomic_set(&ino->count, 0); |
53 | 55 | ||
@@ -158,14 +160,13 @@ void autofs4_kill_sb(struct super_block *sb) | |||
158 | if (!sbi) | 160 | if (!sbi) |
159 | goto out_kill_sb; | 161 | goto out_kill_sb; |
160 | 162 | ||
161 | sb->s_fs_info = NULL; | 163 | if (!sbi->catatonic) |
162 | |||
163 | if ( !sbi->catatonic ) | ||
164 | autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ | 164 | autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ |
165 | 165 | ||
166 | /* Clean up and release dangling references */ | 166 | /* Clean up and release dangling references */ |
167 | autofs4_force_release(sbi); | 167 | autofs4_force_release(sbi); |
168 | 168 | ||
169 | sb->s_fs_info = NULL; | ||
169 | kfree(sbi); | 170 | kfree(sbi); |
170 | 171 | ||
171 | out_kill_sb: | 172 | out_kill_sb: |
@@ -196,7 +197,7 @@ static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
196 | return 0; | 197 | return 0; |
197 | } | 198 | } |
198 | 199 | ||
199 | static struct super_operations autofs4_sops = { | 200 | static const struct super_operations autofs4_sops = { |
200 | .statfs = simple_statfs, | 201 | .statfs = simple_statfs, |
201 | .show_options = autofs4_show_options, | 202 | .show_options = autofs4_show_options, |
202 | }; | 203 | }; |
@@ -336,6 +337,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
336 | mutex_init(&sbi->wq_mutex); | 337 | mutex_init(&sbi->wq_mutex); |
337 | spin_lock_init(&sbi->fs_lock); | 338 | spin_lock_init(&sbi->fs_lock); |
338 | sbi->queues = NULL; | 339 | sbi->queues = NULL; |
340 | spin_lock_init(&sbi->rehash_lock); | ||
341 | INIT_LIST_HEAD(&sbi->rehash_list); | ||
339 | s->s_blocksize = 1024; | 342 | s->s_blocksize = 1024; |
340 | s->s_blocksize_bits = 10; | 343 | s->s_blocksize_bits = 10; |
341 | s->s_magic = AUTOFS_SUPER_MAGIC; | 344 | s->s_magic = AUTOFS_SUPER_MAGIC; |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 8d05b9f7578d..b4631046867e 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -47,7 +47,7 @@ const struct file_operations autofs4_dir_operations = { | |||
47 | .readdir = autofs4_dir_readdir, | 47 | .readdir = autofs4_dir_readdir, |
48 | }; | 48 | }; |
49 | 49 | ||
50 | struct inode_operations autofs4_indirect_root_inode_operations = { | 50 | const struct inode_operations autofs4_indirect_root_inode_operations = { |
51 | .lookup = autofs4_lookup, | 51 | .lookup = autofs4_lookup, |
52 | .unlink = autofs4_dir_unlink, | 52 | .unlink = autofs4_dir_unlink, |
53 | .symlink = autofs4_dir_symlink, | 53 | .symlink = autofs4_dir_symlink, |
@@ -55,7 +55,7 @@ struct inode_operations autofs4_indirect_root_inode_operations = { | |||
55 | .rmdir = autofs4_dir_rmdir, | 55 | .rmdir = autofs4_dir_rmdir, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct inode_operations autofs4_direct_root_inode_operations = { | 58 | const struct inode_operations autofs4_direct_root_inode_operations = { |
59 | .lookup = autofs4_lookup, | 59 | .lookup = autofs4_lookup, |
60 | .unlink = autofs4_dir_unlink, | 60 | .unlink = autofs4_dir_unlink, |
61 | .mkdir = autofs4_dir_mkdir, | 61 | .mkdir = autofs4_dir_mkdir, |
@@ -63,7 +63,7 @@ struct inode_operations autofs4_direct_root_inode_operations = { | |||
63 | .follow_link = autofs4_follow_link, | 63 | .follow_link = autofs4_follow_link, |
64 | }; | 64 | }; |
65 | 65 | ||
66 | struct inode_operations autofs4_dir_inode_operations = { | 66 | const struct inode_operations autofs4_dir_inode_operations = { |
67 | .lookup = autofs4_lookup, | 67 | .lookup = autofs4_lookup, |
68 | .unlink = autofs4_dir_unlink, | 68 | .unlink = autofs4_dir_unlink, |
69 | .symlink = autofs4_dir_symlink, | 69 | .symlink = autofs4_dir_symlink, |
@@ -263,7 +263,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
263 | */ | 263 | */ |
264 | status = d_invalidate(dentry); | 264 | status = d_invalidate(dentry); |
265 | if (status != -EBUSY) | 265 | if (status != -EBUSY) |
266 | return -ENOENT; | 266 | return -EAGAIN; |
267 | } | 267 | } |
268 | 268 | ||
269 | DPRINTK("dentry=%p %.*s ino=%p", | 269 | DPRINTK("dentry=%p %.*s ino=%p", |
@@ -413,7 +413,16 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
413 | */ | 413 | */ |
414 | status = try_to_fill_dentry(dentry, flags); | 414 | status = try_to_fill_dentry(dentry, flags); |
415 | if (status == 0) | 415 | if (status == 0) |
416 | return 1; | 416 | return 1; |
417 | |||
418 | /* | ||
419 | * A status of EAGAIN here means that the dentry has gone | ||
420 | * away while waiting for an expire to complete. If we are | ||
421 | * racing with expire lookup will wait for it so this must | ||
422 | * be a revalidate and we need to send it to lookup. | ||
423 | */ | ||
424 | if (status == -EAGAIN) | ||
425 | return 0; | ||
417 | 426 | ||
418 | return status; | 427 | return status; |
419 | } | 428 | } |
@@ -459,9 +468,18 @@ void autofs4_dentry_release(struct dentry *de) | |||
459 | de->d_fsdata = NULL; | 468 | de->d_fsdata = NULL; |
460 | 469 | ||
461 | if (inf) { | 470 | if (inf) { |
471 | struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); | ||
472 | |||
462 | inf->dentry = NULL; | 473 | inf->dentry = NULL; |
463 | inf->inode = NULL; | 474 | inf->inode = NULL; |
464 | 475 | ||
476 | if (sbi) { | ||
477 | spin_lock(&sbi->rehash_lock); | ||
478 | if (!list_empty(&inf->rehash)) | ||
479 | list_del(&inf->rehash); | ||
480 | spin_unlock(&sbi->rehash_lock); | ||
481 | } | ||
482 | |||
465 | autofs4_free_ino(inf); | 483 | autofs4_free_ino(inf); |
466 | } | 484 | } |
467 | } | 485 | } |
@@ -478,10 +496,80 @@ static struct dentry_operations autofs4_dentry_operations = { | |||
478 | .d_release = autofs4_dentry_release, | 496 | .d_release = autofs4_dentry_release, |
479 | }; | 497 | }; |
480 | 498 | ||
499 | static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name) | ||
500 | { | ||
501 | unsigned int len = name->len; | ||
502 | unsigned int hash = name->hash; | ||
503 | const unsigned char *str = name->name; | ||
504 | struct list_head *p, *head; | ||
505 | |||
506 | spin_lock(&dcache_lock); | ||
507 | spin_lock(&sbi->rehash_lock); | ||
508 | head = &sbi->rehash_list; | ||
509 | list_for_each(p, head) { | ||
510 | struct autofs_info *ino; | ||
511 | struct dentry *dentry; | ||
512 | struct qstr *qstr; | ||
513 | |||
514 | ino = list_entry(p, struct autofs_info, rehash); | ||
515 | dentry = ino->dentry; | ||
516 | |||
517 | spin_lock(&dentry->d_lock); | ||
518 | |||
519 | /* Bad luck, we've already been dentry_iput */ | ||
520 | if (!dentry->d_inode) | ||
521 | goto next; | ||
522 | |||
523 | qstr = &dentry->d_name; | ||
524 | |||
525 | if (dentry->d_name.hash != hash) | ||
526 | goto next; | ||
527 | if (dentry->d_parent != parent) | ||
528 | goto next; | ||
529 | |||
530 | if (qstr->len != len) | ||
531 | goto next; | ||
532 | if (memcmp(qstr->name, str, len)) | ||
533 | goto next; | ||
534 | |||
535 | if (d_unhashed(dentry)) { | ||
536 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
537 | struct inode *inode = dentry->d_inode; | ||
538 | |||
539 | list_del_init(&ino->rehash); | ||
540 | dget(dentry); | ||
541 | /* | ||
542 | * Make the rehashed dentry negative so the VFS | ||
543 | * behaves as it should. | ||
544 | */ | ||
545 | if (inode) { | ||
546 | dentry->d_inode = NULL; | ||
547 | list_del_init(&dentry->d_alias); | ||
548 | spin_unlock(&dentry->d_lock); | ||
549 | spin_unlock(&sbi->rehash_lock); | ||
550 | spin_unlock(&dcache_lock); | ||
551 | iput(inode); | ||
552 | return dentry; | ||
553 | } | ||
554 | spin_unlock(&dentry->d_lock); | ||
555 | spin_unlock(&sbi->rehash_lock); | ||
556 | spin_unlock(&dcache_lock); | ||
557 | return dentry; | ||
558 | } | ||
559 | next: | ||
560 | spin_unlock(&dentry->d_lock); | ||
561 | } | ||
562 | spin_unlock(&sbi->rehash_lock); | ||
563 | spin_unlock(&dcache_lock); | ||
564 | |||
565 | return NULL; | ||
566 | } | ||
567 | |||
481 | /* Lookups in the root directory */ | 568 | /* Lookups in the root directory */ |
482 | static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 569 | static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
483 | { | 570 | { |
484 | struct autofs_sb_info *sbi; | 571 | struct autofs_sb_info *sbi; |
572 | struct dentry *unhashed; | ||
485 | int oz_mode; | 573 | int oz_mode; |
486 | 574 | ||
487 | DPRINTK("name = %.*s", | 575 | DPRINTK("name = %.*s", |
@@ -497,25 +585,46 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
497 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 585 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
498 | current->pid, process_group(current), sbi->catatonic, oz_mode); | 586 | current->pid, process_group(current), sbi->catatonic, oz_mode); |
499 | 587 | ||
500 | /* | 588 | unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name); |
501 | * Mark the dentry incomplete, but add it. This is needed so | 589 | if (!unhashed) { |
502 | * that the VFS layer knows about the dentry, and we can count | 590 | /* |
503 | * on catching any lookups through the revalidate. | 591 | * Mark the dentry incomplete, but add it. This is needed so |
504 | * | 592 | * that the VFS layer knows about the dentry, and we can count |
505 | * Let all the hard work be done by the revalidate function that | 593 | * on catching any lookups through the revalidate. |
506 | * needs to be able to do this anyway.. | 594 | * |
507 | * | 595 | * Let all the hard work be done by the revalidate function that |
508 | * We need to do this before we release the directory semaphore. | 596 | * needs to be able to do this anyway.. |
509 | */ | 597 | * |
510 | dentry->d_op = &autofs4_root_dentry_operations; | 598 | * We need to do this before we release the directory semaphore. |
599 | */ | ||
600 | dentry->d_op = &autofs4_root_dentry_operations; | ||
601 | |||
602 | dentry->d_fsdata = NULL; | ||
603 | d_add(dentry, NULL); | ||
604 | } else { | ||
605 | struct autofs_info *ino = autofs4_dentry_ino(unhashed); | ||
606 | DPRINTK("rehash %p with %p", dentry, unhashed); | ||
607 | /* | ||
608 | * If we are racing with expire the request might not | ||
609 | * be quite complete but the directory has been removed | ||
610 | * so it must have been successful, so just wait for it. | ||
611 | */ | ||
612 | if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { | ||
613 | DPRINTK("wait for incomplete expire %p name=%.*s", | ||
614 | unhashed, unhashed->d_name.len, | ||
615 | unhashed->d_name.name); | ||
616 | autofs4_wait(sbi, unhashed, NFY_NONE); | ||
617 | DPRINTK("request completed"); | ||
618 | } | ||
619 | d_rehash(unhashed); | ||
620 | dentry = unhashed; | ||
621 | } | ||
511 | 622 | ||
512 | if (!oz_mode) { | 623 | if (!oz_mode) { |
513 | spin_lock(&dentry->d_lock); | 624 | spin_lock(&dentry->d_lock); |
514 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; | 625 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; |
515 | spin_unlock(&dentry->d_lock); | 626 | spin_unlock(&dentry->d_lock); |
516 | } | 627 | } |
517 | dentry->d_fsdata = NULL; | ||
518 | d_add(dentry, NULL); | ||
519 | 628 | ||
520 | if (dentry->d_op && dentry->d_op->d_revalidate) { | 629 | if (dentry->d_op && dentry->d_op->d_revalidate) { |
521 | mutex_unlock(&dir->i_mutex); | 630 | mutex_unlock(&dir->i_mutex); |
@@ -534,6 +643,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
534 | if (sigismember (sigset, SIGKILL) || | 643 | if (sigismember (sigset, SIGKILL) || |
535 | sigismember (sigset, SIGQUIT) || | 644 | sigismember (sigset, SIGQUIT) || |
536 | sigismember (sigset, SIGINT)) { | 645 | sigismember (sigset, SIGINT)) { |
646 | if (unhashed) | ||
647 | dput(unhashed); | ||
537 | return ERR_PTR(-ERESTARTNOINTR); | 648 | return ERR_PTR(-ERESTARTNOINTR); |
538 | } | 649 | } |
539 | } | 650 | } |
@@ -544,12 +655,33 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
544 | 655 | ||
545 | /* | 656 | /* |
546 | * If this dentry is unhashed, then we shouldn't honour this | 657 | * If this dentry is unhashed, then we shouldn't honour this |
547 | * lookup even if the dentry is positive. Returning ENOENT here | 658 | * lookup. Returning ENOENT here doesn't do the right thing |
548 | * doesn't do the right thing for all system calls, but it should | 659 | * for all system calls, but it should be OK for the operations |
549 | * be OK for the operations we permit from an autofs. | 660 | * we permit from an autofs. |
550 | */ | 661 | */ |
551 | if (dentry->d_inode && d_unhashed(dentry)) | 662 | if (dentry->d_inode && d_unhashed(dentry)) { |
552 | return ERR_PTR(-ENOENT); | 663 | /* |
664 | * A user space application can (and has done in the past) | ||
665 | * remove and re-create this directory during the callback. | ||
666 | * This can leave us with an unhashed dentry, but a | ||
667 | * successful mount! So we need to perform another | ||
668 | * cached lookup in case the dentry now exists. | ||
669 | */ | ||
670 | struct dentry *parent = dentry->d_parent; | ||
671 | struct dentry *new = d_lookup(parent, &dentry->d_name); | ||
672 | if (new != NULL) | ||
673 | dentry = new; | ||
674 | else | ||
675 | dentry = ERR_PTR(-ENOENT); | ||
676 | |||
677 | if (unhashed) | ||
678 | dput(unhashed); | ||
679 | |||
680 | return dentry; | ||
681 | } | ||
682 | |||
683 | if (unhashed) | ||
684 | return dentry; | ||
553 | 685 | ||
554 | return NULL; | 686 | return NULL; |
555 | } | 687 | } |
@@ -611,9 +743,10 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
611 | * Normal filesystems would do a "d_delete()" to tell the VFS dcache | 743 | * Normal filesystems would do a "d_delete()" to tell the VFS dcache |
612 | * that the file no longer exists. However, doing that means that the | 744 | * that the file no longer exists. However, doing that means that the |
613 | * VFS layer can turn the dentry into a negative dentry. We don't want | 745 | * VFS layer can turn the dentry into a negative dentry. We don't want |
614 | * this, because since the unlink is probably the result of an expire. | 746 | * this, because the unlink is probably the result of an expire. |
615 | * We simply d_drop it, which allows the dentry lookup to remount it | 747 | * We simply d_drop it and add it to a rehash candidates list in the |
616 | * if necessary. | 748 | * super block, which allows the dentry lookup to reuse it retaining |
749 | * the flags, such as expire in progress, in case we're racing with expire. | ||
617 | * | 750 | * |
618 | * If a process is blocked on the dentry waiting for the expire to finish, | 751 | * If a process is blocked on the dentry waiting for the expire to finish, |
619 | * it will invalidate the dentry and try to mount with a new one. | 752 | * it will invalidate the dentry and try to mount with a new one. |
@@ -642,7 +775,14 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) | |||
642 | 775 | ||
643 | dir->i_mtime = CURRENT_TIME; | 776 | dir->i_mtime = CURRENT_TIME; |
644 | 777 | ||
645 | d_drop(dentry); | 778 | spin_lock(&dcache_lock); |
779 | spin_lock(&sbi->rehash_lock); | ||
780 | list_add(&ino->rehash, &sbi->rehash_list); | ||
781 | spin_unlock(&sbi->rehash_lock); | ||
782 | spin_lock(&dentry->d_lock); | ||
783 | __d_drop(dentry); | ||
784 | spin_unlock(&dentry->d_lock); | ||
785 | spin_unlock(&dcache_lock); | ||
646 | 786 | ||
647 | return 0; | 787 | return 0; |
648 | } | 788 | } |
@@ -653,6 +793,9 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
653 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 793 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
654 | struct autofs_info *p_ino; | 794 | struct autofs_info *p_ino; |
655 | 795 | ||
796 | DPRINTK("dentry %p, removing %.*s", | ||
797 | dentry, dentry->d_name.len, dentry->d_name.name); | ||
798 | |||
656 | if (!autofs4_oz_mode(sbi)) | 799 | if (!autofs4_oz_mode(sbi)) |
657 | return -EACCES; | 800 | return -EACCES; |
658 | 801 | ||
@@ -661,6 +804,9 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
661 | spin_unlock(&dcache_lock); | 804 | spin_unlock(&dcache_lock); |
662 | return -ENOTEMPTY; | 805 | return -ENOTEMPTY; |
663 | } | 806 | } |
807 | spin_lock(&sbi->rehash_lock); | ||
808 | list_add(&ino->rehash, &sbi->rehash_list); | ||
809 | spin_unlock(&sbi->rehash_lock); | ||
664 | spin_lock(&dentry->d_lock); | 810 | spin_lock(&dentry->d_lock); |
665 | __d_drop(dentry); | 811 | __d_drop(dentry); |
666 | spin_unlock(&dentry->d_lock); | 812 | spin_unlock(&dentry->d_lock); |
diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index 2ea2c98fd84b..b4ea82934d2e 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c | |||
@@ -19,7 +19,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
19 | return NULL; | 19 | return NULL; |
20 | } | 20 | } |
21 | 21 | ||
22 | struct inode_operations autofs4_symlink_inode_operations = { | 22 | const struct inode_operations autofs4_symlink_inode_operations = { |
23 | .readlink = generic_readlink, | 23 | .readlink = generic_readlink, |
24 | .follow_link = autofs4_follow_link | 24 | .follow_link = autofs4_follow_link |
25 | }; | 25 | }; |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 1e4a539f4417..0d041a9cb348 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -84,7 +84,11 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
84 | struct autofs_wait_queue *wq, | 84 | struct autofs_wait_queue *wq, |
85 | int type) | 85 | int type) |
86 | { | 86 | { |
87 | union autofs_packet_union pkt; | 87 | union { |
88 | struct autofs_packet_hdr hdr; | ||
89 | union autofs_packet_union v4_pkt; | ||
90 | union autofs_v5_packet_union v5_pkt; | ||
91 | } pkt; | ||
88 | size_t pktsz; | 92 | size_t pktsz; |
89 | 93 | ||
90 | DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d", | 94 | DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d", |
@@ -98,7 +102,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
98 | /* Kernel protocol v4 missing and expire packets */ | 102 | /* Kernel protocol v4 missing and expire packets */ |
99 | case autofs_ptype_missing: | 103 | case autofs_ptype_missing: |
100 | { | 104 | { |
101 | struct autofs_packet_missing *mp = &pkt.missing; | 105 | struct autofs_packet_missing *mp = &pkt.v4_pkt.missing; |
102 | 106 | ||
103 | pktsz = sizeof(*mp); | 107 | pktsz = sizeof(*mp); |
104 | 108 | ||
@@ -110,7 +114,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
110 | } | 114 | } |
111 | case autofs_ptype_expire_multi: | 115 | case autofs_ptype_expire_multi: |
112 | { | 116 | { |
113 | struct autofs_packet_expire_multi *ep = &pkt.expire_multi; | 117 | struct autofs_packet_expire_multi *ep = &pkt.v4_pkt.expire_multi; |
114 | 118 | ||
115 | pktsz = sizeof(*ep); | 119 | pktsz = sizeof(*ep); |
116 | 120 | ||
@@ -129,7 +133,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
129 | case autofs_ptype_missing_direct: | 133 | case autofs_ptype_missing_direct: |
130 | case autofs_ptype_expire_direct: | 134 | case autofs_ptype_expire_direct: |
131 | { | 135 | { |
132 | struct autofs_v5_packet *packet = &pkt.v5_packet; | 136 | struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet; |
133 | 137 | ||
134 | pktsz = sizeof(*packet); | 138 | pktsz = sizeof(*packet); |
135 | 139 | ||
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 869f5193ecc2..efeab2fab40b 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
@@ -291,7 +291,7 @@ static int bad_inode_removexattr(struct dentry *dentry, const char *name) | |||
291 | return -EIO; | 291 | return -EIO; |
292 | } | 292 | } |
293 | 293 | ||
294 | static struct inode_operations bad_inode_ops = | 294 | static const struct inode_operations bad_inode_ops = |
295 | { | 295 | { |
296 | .create = bad_inode_create, | 296 | .create = bad_inode_create, |
297 | .lookup = bad_inode_lookup, | 297 | .lookup = bad_inode_lookup, |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 481e59b9d91c..cc6cc8ed2e39 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -68,7 +68,7 @@ static const struct file_operations befs_dir_operations = { | |||
68 | .readdir = befs_readdir, | 68 | .readdir = befs_readdir, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static struct inode_operations befs_dir_inode_operations = { | 71 | static const struct inode_operations befs_dir_inode_operations = { |
72 | .lookup = befs_lookup, | 72 | .lookup = befs_lookup, |
73 | }; | 73 | }; |
74 | 74 | ||
@@ -78,7 +78,7 @@ static const struct address_space_operations befs_aops = { | |||
78 | .bmap = befs_bmap, | 78 | .bmap = befs_bmap, |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static struct inode_operations befs_symlink_inode_operations = { | 81 | static const struct inode_operations befs_symlink_inode_operations = { |
82 | .readlink = generic_readlink, | 82 | .readlink = generic_readlink, |
83 | .follow_link = befs_follow_link, | 83 | .follow_link = befs_follow_link, |
84 | .put_link = befs_put_link, | 84 | .put_link = befs_put_link, |
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h index 31973bbbf057..130f6c66c5ba 100644 --- a/fs/bfs/bfs.h +++ b/fs/bfs/bfs.h | |||
@@ -48,12 +48,12 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode) | |||
48 | 48 | ||
49 | 49 | ||
50 | /* file.c */ | 50 | /* file.c */ |
51 | extern struct inode_operations bfs_file_inops; | 51 | extern const struct inode_operations bfs_file_inops; |
52 | extern const struct file_operations bfs_file_operations; | 52 | extern const struct file_operations bfs_file_operations; |
53 | extern const struct address_space_operations bfs_aops; | 53 | extern const struct address_space_operations bfs_aops; |
54 | 54 | ||
55 | /* dir.c */ | 55 | /* dir.c */ |
56 | extern struct inode_operations bfs_dir_inops; | 56 | extern const struct inode_operations bfs_dir_inops; |
57 | extern const struct file_operations bfs_dir_operations; | 57 | extern const struct file_operations bfs_dir_operations; |
58 | 58 | ||
59 | #endif /* _FS_BFS_BFS_H */ | 59 | #endif /* _FS_BFS_BFS_H */ |
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 2a746e688df5..097f1497f743 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
@@ -260,7 +260,7 @@ end_rename: | |||
260 | return error; | 260 | return error; |
261 | } | 261 | } |
262 | 262 | ||
263 | struct inode_operations bfs_dir_inops = { | 263 | const struct inode_operations bfs_dir_inops = { |
264 | .create = bfs_create, | 264 | .create = bfs_create, |
265 | .lookup = bfs_lookup, | 265 | .lookup = bfs_lookup, |
266 | .link = bfs_link, | 266 | .link = bfs_link, |
diff --git a/fs/bfs/file.c b/fs/bfs/file.c index a9164a87f8de..ef4d1fa04e65 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c | |||
@@ -164,4 +164,4 @@ const struct address_space_operations bfs_aops = { | |||
164 | .bmap = bfs_bmap, | 164 | .bmap = bfs_bmap, |
165 | }; | 165 | }; |
166 | 166 | ||
167 | struct inode_operations bfs_file_inops; | 167 | const struct inode_operations bfs_file_inops; |
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 134c99941a63..93d6219243ad 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c | |||
@@ -270,7 +270,7 @@ static void destroy_inodecache(void) | |||
270 | kmem_cache_destroy(bfs_inode_cachep); | 270 | kmem_cache_destroy(bfs_inode_cachep); |
271 | } | 271 | } |
272 | 272 | ||
273 | static struct super_operations bfs_sops = { | 273 | static const struct super_operations bfs_sops = { |
274 | .alloc_inode = bfs_alloc_inode, | 274 | .alloc_inode = bfs_alloc_inode, |
275 | .destroy_inode = bfs_destroy_inode, | 275 | .destroy_inode = bfs_destroy_inode, |
276 | .read_inode = bfs_read_inode, | 276 | .read_inode = bfs_read_inode, |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 669dbe5b0317..51db1182b27e 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -76,7 +76,8 @@ static struct linux_binfmt elf_format = { | |||
76 | .load_binary = load_elf_binary, | 76 | .load_binary = load_elf_binary, |
77 | .load_shlib = load_elf_library, | 77 | .load_shlib = load_elf_library, |
78 | .core_dump = elf_core_dump, | 78 | .core_dump = elf_core_dump, |
79 | .min_coredump = ELF_EXEC_PAGESIZE | 79 | .min_coredump = ELF_EXEC_PAGESIZE, |
80 | .hasvdso = 1 | ||
80 | }; | 81 | }; |
81 | 82 | ||
82 | #define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE) | 83 | #define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE) |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index a4d933a51208..5810aa1339fd 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -372,7 +372,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
372 | down_write(¤t->mm->mmap_sem); | 372 | down_write(¤t->mm->mmap_sem); |
373 | current->mm->start_brk = do_mmap(NULL, 0, stack_size, | 373 | current->mm->start_brk = do_mmap(NULL, 0, stack_size, |
374 | PROT_READ | PROT_WRITE | PROT_EXEC, | 374 | PROT_READ | PROT_WRITE | PROT_EXEC, |
375 | MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, | 375 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, |
376 | 0); | 376 | 0); |
377 | 377 | ||
378 | if (IS_ERR_VALUE(current->mm->start_brk)) { | 378 | if (IS_ERR_VALUE(current->mm->start_brk)) { |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index ae8595d49856..7b0265d7f3a8 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -419,7 +419,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
419 | unsigned long textpos = 0, datapos = 0, result; | 419 | unsigned long textpos = 0, datapos = 0, result; |
420 | unsigned long realdatastart = 0; | 420 | unsigned long realdatastart = 0; |
421 | unsigned long text_len, data_len, bss_len, stack_len, flags; | 421 | unsigned long text_len, data_len, bss_len, stack_len, flags; |
422 | unsigned long memp = 0; /* for finding the brk area */ | 422 | unsigned long len, reallen, memp = 0; |
423 | unsigned long extra, rlim; | 423 | unsigned long extra, rlim; |
424 | unsigned long *reloc = 0, *rp; | 424 | unsigned long *reloc = 0, *rp; |
425 | struct inode *inode; | 425 | struct inode *inode; |
@@ -540,10 +540,18 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
540 | goto err; | 540 | goto err; |
541 | } | 541 | } |
542 | 542 | ||
543 | len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | ||
543 | down_write(¤t->mm->mmap_sem); | 544 | down_write(¤t->mm->mmap_sem); |
544 | realdatastart = do_mmap(0, 0, data_len + extra + | 545 | realdatastart = do_mmap(0, 0, len, |
545 | MAX_SHARED_LIBS * sizeof(unsigned long), | 546 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); |
546 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); | 547 | /* Remap to use all availabe slack region space */ |
548 | if (realdatastart && (realdatastart < (unsigned long)-4096)) { | ||
549 | reallen = ksize(realdatastart); | ||
550 | if (reallen > len) { | ||
551 | realdatastart = do_mremap(realdatastart, len, | ||
552 | reallen, MREMAP_FIXED, realdatastart); | ||
553 | } | ||
554 | } | ||
547 | up_write(¤t->mm->mmap_sem); | 555 | up_write(¤t->mm->mmap_sem); |
548 | 556 | ||
549 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { | 557 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { |
@@ -584,11 +592,20 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
584 | 592 | ||
585 | } else { | 593 | } else { |
586 | 594 | ||
595 | len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | ||
587 | down_write(¤t->mm->mmap_sem); | 596 | down_write(¤t->mm->mmap_sem); |
588 | textpos = do_mmap(0, 0, text_len + data_len + extra + | 597 | textpos = do_mmap(0, 0, len, |
589 | MAX_SHARED_LIBS * sizeof(unsigned long), | 598 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); |
590 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); | 599 | /* Remap to use all availabe slack region space */ |
600 | if (textpos && (textpos < (unsigned long) -4096)) { | ||
601 | reallen = ksize(textpos); | ||
602 | if (reallen > len) { | ||
603 | textpos = do_mremap(textpos, len, reallen, | ||
604 | MREMAP_FIXED, textpos); | ||
605 | } | ||
606 | } | ||
591 | up_write(¤t->mm->mmap_sem); | 607 | up_write(¤t->mm->mmap_sem); |
608 | |||
592 | if (!textpos || textpos >= (unsigned long) -4096) { | 609 | if (!textpos || textpos >= (unsigned long) -4096) { |
593 | if (!textpos) | 610 | if (!textpos) |
594 | textpos = (unsigned long) -ENOMEM; | 611 | textpos = (unsigned long) -ENOMEM; |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index c2e08252af35..e6f57990b121 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -719,7 +719,7 @@ static const struct file_operations bm_status_operations = { | |||
719 | 719 | ||
720 | /* Superblock handling */ | 720 | /* Superblock handling */ |
721 | 721 | ||
722 | static struct super_operations s_ops = { | 722 | static const struct super_operations s_ops = { |
723 | .statfs = simple_statfs, | 723 | .statfs = simple_statfs, |
724 | .clear_inode = bm_clear_inode, | 724 | .clear_inode = bm_clear_inode, |
725 | }; | 725 | }; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index fc7028b685f2..575076c018f4 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -489,7 +489,7 @@ static void bdev_clear_inode(struct inode *inode) | |||
489 | spin_unlock(&bdev_lock); | 489 | spin_unlock(&bdev_lock); |
490 | } | 490 | } |
491 | 491 | ||
492 | static struct super_operations bdev_sops = { | 492 | static const struct super_operations bdev_sops = { |
493 | .statfs = simple_statfs, | 493 | .statfs = simple_statfs, |
494 | .alloc_inode = bdev_alloc_inode, | 494 | .alloc_inode = bdev_alloc_inode, |
495 | .destroy_inode = bdev_destroy_inode, | 495 | .destroy_inode = bdev_destroy_inode, |
@@ -1101,6 +1101,13 @@ static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, | |||
1101 | int for_part); | 1101 | int for_part); |
1102 | static int __blkdev_put(struct block_device *bdev, int for_part); | 1102 | static int __blkdev_put(struct block_device *bdev, int for_part); |
1103 | 1103 | ||
1104 | /* | ||
1105 | * bd_mutex locking: | ||
1106 | * | ||
1107 | * mutex_lock(part->bd_mutex) | ||
1108 | * mutex_lock_nested(whole->bd_mutex, 1) | ||
1109 | */ | ||
1110 | |||
1104 | static int do_open(struct block_device *bdev, struct file *file, int for_part) | 1111 | static int do_open(struct block_device *bdev, struct file *file, int for_part) |
1105 | { | 1112 | { |
1106 | struct module *owner = NULL; | 1113 | struct module *owner = NULL; |
diff --git a/fs/buffer.c b/fs/buffer.c index 1ad674fd348c..e8504b65176c 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -78,6 +78,7 @@ EXPORT_SYMBOL(__lock_buffer); | |||
78 | 78 | ||
79 | void fastcall unlock_buffer(struct buffer_head *bh) | 79 | void fastcall unlock_buffer(struct buffer_head *bh) |
80 | { | 80 | { |
81 | smp_mb__before_clear_bit(); | ||
81 | clear_buffer_locked(bh); | 82 | clear_buffer_locked(bh); |
82 | smp_mb__after_clear_bit(); | 83 | smp_mb__after_clear_bit(); |
83 | wake_up_bit(&bh->b_state, BH_Lock); | 84 | wake_up_bit(&bh->b_state, BH_Lock); |
@@ -345,7 +346,7 @@ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) | |||
345 | * We really want to use invalidate_inode_pages2() for | 346 | * We really want to use invalidate_inode_pages2() for |
346 | * that, but not until that's cleaned up. | 347 | * that, but not until that's cleaned up. |
347 | */ | 348 | */ |
348 | invalidate_inode_pages(mapping); | 349 | invalidate_mapping_pages(mapping, 0, -1); |
349 | } | 350 | } |
350 | 351 | ||
351 | /* | 352 | /* |
@@ -1282,11 +1283,11 @@ static void bh_lru_install(struct buffer_head *bh) | |||
1282 | * Look up the bh in this cpu's LRU. If it's there, move it to the head. | 1283 | * Look up the bh in this cpu's LRU. If it's there, move it to the head. |
1283 | */ | 1284 | */ |
1284 | static struct buffer_head * | 1285 | static struct buffer_head * |
1285 | lookup_bh_lru(struct block_device *bdev, sector_t block, int size) | 1286 | lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size) |
1286 | { | 1287 | { |
1287 | struct buffer_head *ret = NULL; | 1288 | struct buffer_head *ret = NULL; |
1288 | struct bh_lru *lru; | 1289 | struct bh_lru *lru; |
1289 | int i; | 1290 | unsigned int i; |
1290 | 1291 | ||
1291 | check_irqs_on(); | 1292 | check_irqs_on(); |
1292 | bh_lru_lock(); | 1293 | bh_lru_lock(); |
@@ -1318,7 +1319,7 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, int size) | |||
1318 | * NULL | 1319 | * NULL |
1319 | */ | 1320 | */ |
1320 | struct buffer_head * | 1321 | struct buffer_head * |
1321 | __find_get_block(struct block_device *bdev, sector_t block, int size) | 1322 | __find_get_block(struct block_device *bdev, sector_t block, unsigned size) |
1322 | { | 1323 | { |
1323 | struct buffer_head *bh = lookup_bh_lru(bdev, block, size); | 1324 | struct buffer_head *bh = lookup_bh_lru(bdev, block, size); |
1324 | 1325 | ||
@@ -1346,7 +1347,7 @@ EXPORT_SYMBOL(__find_get_block); | |||
1346 | * attempt is failing. FIXME, perhaps? | 1347 | * attempt is failing. FIXME, perhaps? |
1347 | */ | 1348 | */ |
1348 | struct buffer_head * | 1349 | struct buffer_head * |
1349 | __getblk(struct block_device *bdev, sector_t block, int size) | 1350 | __getblk(struct block_device *bdev, sector_t block, unsigned size) |
1350 | { | 1351 | { |
1351 | struct buffer_head *bh = __find_get_block(bdev, block, size); | 1352 | struct buffer_head *bh = __find_get_block(bdev, block, size); |
1352 | 1353 | ||
@@ -1360,7 +1361,7 @@ EXPORT_SYMBOL(__getblk); | |||
1360 | /* | 1361 | /* |
1361 | * Do async read-ahead on a buffer.. | 1362 | * Do async read-ahead on a buffer.. |
1362 | */ | 1363 | */ |
1363 | void __breadahead(struct block_device *bdev, sector_t block, int size) | 1364 | void __breadahead(struct block_device *bdev, sector_t block, unsigned size) |
1364 | { | 1365 | { |
1365 | struct buffer_head *bh = __getblk(bdev, block, size); | 1366 | struct buffer_head *bh = __getblk(bdev, block, size); |
1366 | if (likely(bh)) { | 1367 | if (likely(bh)) { |
@@ -1380,7 +1381,7 @@ EXPORT_SYMBOL(__breadahead); | |||
1380 | * It returns NULL if the block was unreadable. | 1381 | * It returns NULL if the block was unreadable. |
1381 | */ | 1382 | */ |
1382 | struct buffer_head * | 1383 | struct buffer_head * |
1383 | __bread(struct block_device *bdev, sector_t block, int size) | 1384 | __bread(struct block_device *bdev, sector_t block, unsigned size) |
1384 | { | 1385 | { |
1385 | struct buffer_head *bh = __getblk(bdev, block, size); | 1386 | struct buffer_head *bh = __getblk(bdev, block, size); |
1386 | 1387 | ||
@@ -1439,6 +1440,7 @@ static void discard_buffer(struct buffer_head * bh) | |||
1439 | clear_buffer_req(bh); | 1440 | clear_buffer_req(bh); |
1440 | clear_buffer_new(bh); | 1441 | clear_buffer_new(bh); |
1441 | clear_buffer_delay(bh); | 1442 | clear_buffer_delay(bh); |
1443 | clear_buffer_unwritten(bh); | ||
1442 | unlock_buffer(bh); | 1444 | unlock_buffer(bh); |
1443 | } | 1445 | } |
1444 | 1446 | ||
@@ -1741,7 +1743,6 @@ recover: | |||
1741 | SetPageError(page); | 1743 | SetPageError(page); |
1742 | BUG_ON(PageWriteback(page)); | 1744 | BUG_ON(PageWriteback(page)); |
1743 | set_page_writeback(page); | 1745 | set_page_writeback(page); |
1744 | unlock_page(page); | ||
1745 | do { | 1746 | do { |
1746 | struct buffer_head *next = bh->b_this_page; | 1747 | struct buffer_head *next = bh->b_this_page; |
1747 | if (buffer_async_write(bh)) { | 1748 | if (buffer_async_write(bh)) { |
@@ -1751,6 +1752,7 @@ recover: | |||
1751 | } | 1752 | } |
1752 | bh = next; | 1753 | bh = next; |
1753 | } while (bh != head); | 1754 | } while (bh != head); |
1755 | unlock_page(page); | ||
1754 | goto done; | 1756 | goto done; |
1755 | } | 1757 | } |
1756 | 1758 | ||
@@ -1822,6 +1824,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page, | |||
1822 | continue; | 1824 | continue; |
1823 | } | 1825 | } |
1824 | if (!buffer_uptodate(bh) && !buffer_delay(bh) && | 1826 | if (!buffer_uptodate(bh) && !buffer_delay(bh) && |
1827 | !buffer_unwritten(bh) && | ||
1825 | (block_start < from || block_end > to)) { | 1828 | (block_start < from || block_end > to)) { |
1826 | ll_rw_block(READ, 1, &bh); | 1829 | ll_rw_block(READ, 1, &bh); |
1827 | *wait_bh++=bh; | 1830 | *wait_bh++=bh; |
@@ -2245,7 +2248,6 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to, | |||
2245 | int i; | 2248 | int i; |
2246 | int ret = 0; | 2249 | int ret = 0; |
2247 | int is_mapped_to_disk = 1; | 2250 | int is_mapped_to_disk = 1; |
2248 | int dirtied_it = 0; | ||
2249 | 2251 | ||
2250 | if (PageMappedToDisk(page)) | 2252 | if (PageMappedToDisk(page)) |
2251 | return 0; | 2253 | return 0; |
@@ -2282,14 +2284,10 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to, | |||
2282 | continue; | 2284 | continue; |
2283 | if (buffer_new(&map_bh) || !buffer_mapped(&map_bh)) { | 2285 | if (buffer_new(&map_bh) || !buffer_mapped(&map_bh)) { |
2284 | kaddr = kmap_atomic(page, KM_USER0); | 2286 | kaddr = kmap_atomic(page, KM_USER0); |
2285 | if (block_start < from) { | 2287 | if (block_start < from) |
2286 | memset(kaddr+block_start, 0, from-block_start); | 2288 | memset(kaddr+block_start, 0, from-block_start); |
2287 | dirtied_it = 1; | 2289 | if (block_end > to) |
2288 | } | ||
2289 | if (block_end > to) { | ||
2290 | memset(kaddr + to, 0, block_end - to); | 2290 | memset(kaddr + to, 0, block_end - to); |
2291 | dirtied_it = 1; | ||
2292 | } | ||
2293 | flush_dcache_page(page); | 2291 | flush_dcache_page(page); |
2294 | kunmap_atomic(kaddr, KM_USER0); | 2292 | kunmap_atomic(kaddr, KM_USER0); |
2295 | continue; | 2293 | continue; |
@@ -2344,17 +2342,6 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to, | |||
2344 | 2342 | ||
2345 | if (is_mapped_to_disk) | 2343 | if (is_mapped_to_disk) |
2346 | SetPageMappedToDisk(page); | 2344 | SetPageMappedToDisk(page); |
2347 | SetPageUptodate(page); | ||
2348 | |||
2349 | /* | ||
2350 | * Setting the page dirty here isn't necessary for the prepare_write | ||
2351 | * function - commit_write will do that. But if/when this function is | ||
2352 | * used within the pagefault handler to ensure that all mmapped pages | ||
2353 | * have backing space in the filesystem, we will need to dirty the page | ||
2354 | * if its contents were altered. | ||
2355 | */ | ||
2356 | if (dirtied_it) | ||
2357 | set_page_dirty(page); | ||
2358 | 2345 | ||
2359 | return 0; | 2346 | return 0; |
2360 | 2347 | ||
@@ -2384,6 +2371,7 @@ int nobh_commit_write(struct file *file, struct page *page, | |||
2384 | struct inode *inode = page->mapping->host; | 2371 | struct inode *inode = page->mapping->host; |
2385 | loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; | 2372 | loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; |
2386 | 2373 | ||
2374 | SetPageUptodate(page); | ||
2387 | set_page_dirty(page); | 2375 | set_page_dirty(page); |
2388 | if (pos > inode->i_size) { | 2376 | if (pos > inode->i_size) { |
2389 | i_size_write(inode, pos); | 2377 | i_size_write(inode, pos); |
@@ -2543,7 +2531,7 @@ int block_truncate_page(struct address_space *mapping, | |||
2543 | if (PageUptodate(page)) | 2531 | if (PageUptodate(page)) |
2544 | set_buffer_uptodate(bh); | 2532 | set_buffer_uptodate(bh); |
2545 | 2533 | ||
2546 | if (!buffer_uptodate(bh) && !buffer_delay(bh)) { | 2534 | if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) { |
2547 | err = -EIO; | 2535 | err = -EIO; |
2548 | ll_rw_block(READ, 1, &bh); | 2536 | ll_rw_block(READ, 1, &bh); |
2549 | wait_on_buffer(bh); | 2537 | wait_on_buffer(bh); |
diff --git a/fs/char_dev.c b/fs/char_dev.c index a885f46ca001..78ced721554d 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
9 | #include <linux/kdev_t.h> | ||
9 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
10 | #include <linux/string.h> | 11 | #include <linux/string.h> |
11 | 12 | ||
@@ -108,6 +109,8 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, | |||
108 | /* temporary */ | 109 | /* temporary */ |
109 | if (major == 0) { | 110 | if (major == 0) { |
110 | for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { | 111 | for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { |
112 | if (is_lanana_major(i)) | ||
113 | continue; | ||
111 | if (chrdevs[i] == NULL) | 114 | if (chrdevs[i] == NULL) |
112 | break; | 115 | break; |
113 | } | 116 | } |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 85e3850bf2c9..5fe13593b57f 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,8 +1,15 @@ | |||
1 | Version 1.47 | 1 | Version 1.47 |
2 | ------------ | 2 | ------------ |
3 | Fix oops in list_del during mount caused by unaligned string. | 3 | Fix oops in list_del during mount caused by unaligned string. |
4 | Fix file corruption which could occur on some large file | ||
5 | copies caused by writepages page i/o completion bug. | ||
4 | Seek to SEEK_END forces check for update of file size for non-cached | 6 | Seek to SEEK_END forces check for update of file size for non-cached |
5 | files. | 7 | files. Allow file size to be updated on remote extend of locally open, |
8 | non-cached file. Fix reconnect to newer Samba servers (or other servers | ||
9 | which support the CIFS Unix/POSIX extensions) so that we again tell the | ||
10 | server the Unix/POSIX cifs capabilities which we support (SetFSInfo). | ||
11 | Add experimental support for new POSIX Open/Mkdir (which returns | ||
12 | stat information on the open, and allows setting the mode). | ||
6 | 13 | ||
7 | Version 1.46 | 14 | Version 1.46 |
8 | ------------ | 15 | ------------ |
diff --git a/fs/cifs/README b/fs/cifs/README index 432e515431c4..080c5eba112b 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -1,5 +1,5 @@ | |||
1 | The CIFS VFS support for Linux supports many advanced network filesystem | 1 | The CIFS VFS support for Linux supports many advanced network filesystem |
2 | features such as heirarchical dfs like namespace, hardlinks, locking and more. | 2 | features such as hierarchical dfs like namespace, hardlinks, locking and more. |
3 | It was designed to comply with the SNIA CIFS Technical Reference (which | 3 | It was designed to comply with the SNIA CIFS Technical Reference (which |
4 | supersedes the 1992 X/Open SMB Standard) as well as to perform best practice | 4 | supersedes the 1992 X/Open SMB Standard) as well as to perform best practice |
5 | practical interoperability with Windows 2000, Windows XP, Samba and equivalent | 5 | practical interoperability with Windows 2000, Windows XP, Samba and equivalent |
diff --git a/fs/cifs/TODO b/fs/cifs/TODO index fc34c74ec4be..68372946dc92 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO | |||
@@ -128,3 +128,11 @@ negotiated size) and send larger write sizes to modern servers. | |||
128 | 128 | ||
129 | 4) More exhaustively test against less common servers. More testing | 129 | 4) More exhaustively test against less common servers. More testing |
130 | against Windows 9x, Windows ME servers. | 130 | against Windows 9x, Windows ME servers. |
131 | |||
132 | DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too) | ||
133 | |||
134 | mount check for unmatched uids - and uid override | ||
135 | |||
136 | Add mount option for Linux extension disable per mount, and partial disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?) | ||
137 | |||
138 | Free threads at umount --force that are stuck on the sesSem | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 93ef09971d2f..bc2c0ac27169 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -64,7 +64,7 @@ extern struct task_struct * oplockThread; /* remove sparse warning */ | |||
64 | struct task_struct * oplockThread = NULL; | 64 | struct task_struct * oplockThread = NULL; |
65 | extern struct task_struct * dnotifyThread; /* remove sparse warning */ | 65 | extern struct task_struct * dnotifyThread; /* remove sparse warning */ |
66 | struct task_struct * dnotifyThread = NULL; | 66 | struct task_struct * dnotifyThread = NULL; |
67 | static struct super_operations cifs_super_ops; | 67 | static const struct super_operations cifs_super_ops; |
68 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; | 68 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; |
69 | module_param(CIFSMaxBufSize, int, 0); | 69 | module_param(CIFSMaxBufSize, int, 0); |
70 | MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); | 70 | MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); |
@@ -91,8 +91,9 @@ cifs_read_super(struct super_block *sb, void *data, | |||
91 | struct inode *inode; | 91 | struct inode *inode; |
92 | struct cifs_sb_info *cifs_sb; | 92 | struct cifs_sb_info *cifs_sb; |
93 | int rc = 0; | 93 | int rc = 0; |
94 | 94 | ||
95 | sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ | 95 | /* BB should we make this contingent on mount parm? */ |
96 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; | ||
96 | sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); | 97 | sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); |
97 | cifs_sb = CIFS_SB(sb); | 98 | cifs_sb = CIFS_SB(sb); |
98 | if(cifs_sb == NULL) | 99 | if(cifs_sb == NULL) |
@@ -258,7 +259,10 @@ cifs_alloc_inode(struct super_block *sb) | |||
258 | cifs_inode->clientCanCacheRead = FALSE; | 259 | cifs_inode->clientCanCacheRead = FALSE; |
259 | cifs_inode->clientCanCacheAll = FALSE; | 260 | cifs_inode->clientCanCacheAll = FALSE; |
260 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ | 261 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ |
261 | cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; | 262 | |
263 | /* Can not set i_flags here - they get immediately overwritten | ||
264 | to zero by the VFS */ | ||
265 | /* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/ | ||
262 | INIT_LIST_HEAD(&cifs_inode->openFileList); | 266 | INIT_LIST_HEAD(&cifs_inode->openFileList); |
263 | return &cifs_inode->vfs_inode; | 267 | return &cifs_inode->vfs_inode; |
264 | } | 268 | } |
@@ -283,6 +287,7 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
283 | 287 | ||
284 | if (cifs_sb) { | 288 | if (cifs_sb) { |
285 | if (cifs_sb->tcon) { | 289 | if (cifs_sb->tcon) { |
290 | /* BB add prepath to mount options displayed */ | ||
286 | seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); | 291 | seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); |
287 | if (cifs_sb->tcon->ses) { | 292 | if (cifs_sb->tcon->ses) { |
288 | if (cifs_sb->tcon->ses->userName) | 293 | if (cifs_sb->tcon->ses->userName) |
@@ -453,7 +458,7 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data) | |||
453 | return 0; | 458 | return 0; |
454 | } | 459 | } |
455 | 460 | ||
456 | static struct super_operations cifs_super_ops = { | 461 | static const struct super_operations cifs_super_ops = { |
457 | .read_inode = cifs_read_inode, | 462 | .read_inode = cifs_read_inode, |
458 | .put_super = cifs_put_super, | 463 | .put_super = cifs_put_super, |
459 | .statfs = cifs_statfs, | 464 | .statfs = cifs_statfs, |
@@ -533,7 +538,7 @@ static struct file_system_type cifs_fs_type = { | |||
533 | .kill_sb = kill_anon_super, | 538 | .kill_sb = kill_anon_super, |
534 | /* .fs_flags */ | 539 | /* .fs_flags */ |
535 | }; | 540 | }; |
536 | struct inode_operations cifs_dir_inode_ops = { | 541 | const struct inode_operations cifs_dir_inode_ops = { |
537 | .create = cifs_create, | 542 | .create = cifs_create, |
538 | .lookup = cifs_lookup, | 543 | .lookup = cifs_lookup, |
539 | .getattr = cifs_getattr, | 544 | .getattr = cifs_getattr, |
@@ -555,7 +560,7 @@ struct inode_operations cifs_dir_inode_ops = { | |||
555 | #endif | 560 | #endif |
556 | }; | 561 | }; |
557 | 562 | ||
558 | struct inode_operations cifs_file_inode_ops = { | 563 | const struct inode_operations cifs_file_inode_ops = { |
559 | /* revalidate:cifs_revalidate, */ | 564 | /* revalidate:cifs_revalidate, */ |
560 | .setattr = cifs_setattr, | 565 | .setattr = cifs_setattr, |
561 | .getattr = cifs_getattr, /* do we need this anymore? */ | 566 | .getattr = cifs_getattr, /* do we need this anymore? */ |
@@ -569,7 +574,7 @@ struct inode_operations cifs_file_inode_ops = { | |||
569 | #endif | 574 | #endif |
570 | }; | 575 | }; |
571 | 576 | ||
572 | struct inode_operations cifs_symlink_inode_ops = { | 577 | const struct inode_operations cifs_symlink_inode_ops = { |
573 | .readlink = generic_readlink, | 578 | .readlink = generic_readlink, |
574 | .follow_link = cifs_follow_link, | 579 | .follow_link = cifs_follow_link, |
575 | .put_link = cifs_put_link, | 580 | .put_link = cifs_put_link, |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 8aa66dcf13bd..c97c08eb481a 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -36,13 +36,13 @@ extern const struct address_space_operations cifs_addr_ops; | |||
36 | extern const struct address_space_operations cifs_addr_ops_smallbuf; | 36 | extern const struct address_space_operations cifs_addr_ops_smallbuf; |
37 | 37 | ||
38 | /* Functions related to super block operations */ | 38 | /* Functions related to super block operations */ |
39 | /* extern struct super_operations cifs_super_ops;*/ | 39 | /* extern const struct super_operations cifs_super_ops;*/ |
40 | extern void cifs_read_inode(struct inode *); | 40 | extern void cifs_read_inode(struct inode *); |
41 | extern void cifs_delete_inode(struct inode *); | 41 | extern void cifs_delete_inode(struct inode *); |
42 | /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */ | 42 | /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */ |
43 | 43 | ||
44 | /* Functions related to inodes */ | 44 | /* Functions related to inodes */ |
45 | extern struct inode_operations cifs_dir_inode_ops; | 45 | extern const struct inode_operations cifs_dir_inode_ops; |
46 | extern int cifs_create(struct inode *, struct dentry *, int, | 46 | extern int cifs_create(struct inode *, struct dentry *, int, |
47 | struct nameidata *); | 47 | struct nameidata *); |
48 | extern struct dentry * cifs_lookup(struct inode *, struct dentry *, | 48 | extern struct dentry * cifs_lookup(struct inode *, struct dentry *, |
@@ -58,8 +58,8 @@ extern int cifs_revalidate(struct dentry *); | |||
58 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 58 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
59 | extern int cifs_setattr(struct dentry *, struct iattr *); | 59 | extern int cifs_setattr(struct dentry *, struct iattr *); |
60 | 60 | ||
61 | extern struct inode_operations cifs_file_inode_ops; | 61 | extern const struct inode_operations cifs_file_inode_ops; |
62 | extern struct inode_operations cifs_symlink_inode_ops; | 62 | extern const struct inode_operations cifs_symlink_inode_ops; |
63 | 63 | ||
64 | /* Functions related to files and directories */ | 64 | /* Functions related to files and directories */ |
65 | extern const struct file_operations cifs_file_ops; | 65 | extern const struct file_operations cifs_file_ops; |
@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | |||
100 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 100 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
101 | extern int cifs_ioctl (struct inode * inode, struct file * filep, | 101 | extern int cifs_ioctl (struct inode * inode, struct file * filep, |
102 | unsigned int command, unsigned long arg); | 102 | unsigned int command, unsigned long arg); |
103 | #define CIFS_VERSION "1.47" | 103 | #define CIFS_VERSION "1.48" |
104 | #endif /* _CIFSFS_H */ | 104 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 068ef51edbf7..2498d644827c 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/cifspdu.h | 2 | * fs/cifs/cifspdu.h |
3 | * | 3 | * |
4 | * Copyright (c) International Business Machines Corp., 2002,2005 | 4 | * Copyright (c) International Business Machines Corp., 2002,2007 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
@@ -35,9 +35,11 @@ | |||
35 | #define BAD_PROT 0xFFFF | 35 | #define BAD_PROT 0xFFFF |
36 | 36 | ||
37 | /* SMB command codes */ | 37 | /* SMB command codes */ |
38 | /* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses | 38 | /* |
39 | (ie which include no useful data other than the SMB error code itself). | 39 | * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses |
40 | Knowing this helps avoid response buffer allocations and copy in some cases */ | 40 | * (ie which include no useful data other than the SMB error code itself). |
41 | * Knowing this helps avoid response buffer allocations and copy in some cases | ||
42 | */ | ||
41 | #define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ | 43 | #define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ |
42 | #define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ | 44 | #define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ |
43 | #define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ | 45 | #define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ |
@@ -544,7 +546,8 @@ typedef union smb_com_session_setup_andx { | |||
544 | /* unsigned char * NativeOS; */ | 546 | /* unsigned char * NativeOS; */ |
545 | /* unsigned char * NativeLanMan; */ | 547 | /* unsigned char * NativeLanMan; */ |
546 | /* unsigned char * PrimaryDomain; */ | 548 | /* unsigned char * PrimaryDomain; */ |
547 | } __attribute__((packed)) resp; /* NTLM response with or without extended sec*/ | 549 | } __attribute__((packed)) resp; /* NTLM response |
550 | (with or without extended sec) */ | ||
548 | 551 | ||
549 | struct { /* request format */ | 552 | struct { /* request format */ |
550 | struct smb_hdr hdr; /* wct = 10 */ | 553 | struct smb_hdr hdr; /* wct = 10 */ |
@@ -795,6 +798,8 @@ typedef struct smb_com_openx_rsp { | |||
795 | __u16 ByteCount; | 798 | __u16 ByteCount; |
796 | } __attribute__((packed)) OPENX_RSP; | 799 | } __attribute__((packed)) OPENX_RSP; |
797 | 800 | ||
801 | /* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */ | ||
802 | |||
798 | /* Legacy write request for older servers */ | 803 | /* Legacy write request for older servers */ |
799 | typedef struct smb_com_writex_req { | 804 | typedef struct smb_com_writex_req { |
800 | struct smb_hdr hdr; /* wct = 12 */ | 805 | struct smb_hdr hdr; /* wct = 12 */ |
@@ -1352,11 +1357,13 @@ struct smb_t2_rsp { | |||
1352 | #define SMB_QUERY_FILE_UNIX_BASIC 0x200 | 1357 | #define SMB_QUERY_FILE_UNIX_BASIC 0x200 |
1353 | #define SMB_QUERY_FILE_UNIX_LINK 0x201 | 1358 | #define SMB_QUERY_FILE_UNIX_LINK 0x201 |
1354 | #define SMB_QUERY_POSIX_ACL 0x204 | 1359 | #define SMB_QUERY_POSIX_ACL 0x204 |
1355 | #define SMB_QUERY_XATTR 0x205 | 1360 | #define SMB_QUERY_XATTR 0x205 /* e.g. system EA name space */ |
1356 | #define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ | 1361 | #define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ |
1357 | #define SMB_QUERY_POSIX_PERMISSION 0x207 | 1362 | #define SMB_QUERY_POSIX_PERMISSION 0x207 |
1358 | #define SMB_QUERY_POSIX_LOCK 0x208 | 1363 | #define SMB_QUERY_POSIX_LOCK 0x208 |
1359 | /* #define SMB_POSIX_OPEN 0x209 */ | 1364 | /* #define SMB_POSIX_OPEN 0x209 */ |
1365 | /* #define SMB_POSIX_UNLINK 0x20a */ | ||
1366 | #define SMB_QUERY_FILE__UNIX_INFO2 0x20b | ||
1360 | #define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee | 1367 | #define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee |
1361 | #define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 | 1368 | #define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 |
1362 | #define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ | 1369 | #define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ |
@@ -1377,8 +1384,10 @@ struct smb_t2_rsp { | |||
1377 | #define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ | 1384 | #define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ |
1378 | #define SMB_SET_POSIX_LOCK 0x208 | 1385 | #define SMB_SET_POSIX_LOCK 0x208 |
1379 | #define SMB_POSIX_OPEN 0x209 | 1386 | #define SMB_POSIX_OPEN 0x209 |
1387 | #define SMB_POSIX_UNLINK 0x20a | ||
1388 | #define SMB_SET_FILE_UNIX_INFO2 | ||
1380 | #define SMB_SET_FILE_BASIC_INFO2 0x3ec | 1389 | #define SMB_SET_FILE_BASIC_INFO2 0x3ec |
1381 | #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ | 1390 | #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */ |
1382 | #define SMB_FILE_ALL_INFO2 0x3fa | 1391 | #define SMB_FILE_ALL_INFO2 0x3fa |
1383 | #define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb | 1392 | #define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb |
1384 | #define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc | 1393 | #define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc |
@@ -1428,7 +1437,7 @@ typedef struct smb_com_transaction2_qpi_rsp { | |||
1428 | struct smb_hdr hdr; /* wct = 10 + SetupCount */ | 1437 | struct smb_hdr hdr; /* wct = 10 + SetupCount */ |
1429 | struct trans2_resp t2; | 1438 | struct trans2_resp t2; |
1430 | __u16 ByteCount; | 1439 | __u16 ByteCount; |
1431 | __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ | 1440 | __u16 Reserved2; /* parameter word is present for infolevels > 100 */ |
1432 | } __attribute__((packed)) TRANSACTION2_QPI_RSP; | 1441 | } __attribute__((packed)) TRANSACTION2_QPI_RSP; |
1433 | 1442 | ||
1434 | typedef struct smb_com_transaction2_spi_req { | 1443 | typedef struct smb_com_transaction2_spi_req { |
@@ -1461,7 +1470,7 @@ typedef struct smb_com_transaction2_spi_rsp { | |||
1461 | struct smb_hdr hdr; /* wct = 10 + SetupCount */ | 1470 | struct smb_hdr hdr; /* wct = 10 + SetupCount */ |
1462 | struct trans2_resp t2; | 1471 | struct trans2_resp t2; |
1463 | __u16 ByteCount; | 1472 | __u16 ByteCount; |
1464 | __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ | 1473 | __u16 Reserved2; /* parameter word is present for infolevels > 100 */ |
1465 | } __attribute__((packed)) TRANSACTION2_SPI_RSP; | 1474 | } __attribute__((packed)) TRANSACTION2_SPI_RSP; |
1466 | 1475 | ||
1467 | struct set_file_rename { | 1476 | struct set_file_rename { |
@@ -1627,6 +1636,7 @@ typedef struct smb_com_transaction2_fnext_rsp_parms { | |||
1627 | #define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105 | 1636 | #define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105 |
1628 | #define SMB_QUERY_CIFS_UNIX_INFO 0x200 | 1637 | #define SMB_QUERY_CIFS_UNIX_INFO 0x200 |
1629 | #define SMB_QUERY_POSIX_FS_INFO 0x201 | 1638 | #define SMB_QUERY_POSIX_FS_INFO 0x201 |
1639 | #define SMB_QUERY_POSIX_WHO_AM_I 0x202 | ||
1630 | #define SMB_QUERY_LABEL_INFO 0x3ea | 1640 | #define SMB_QUERY_LABEL_INFO 0x3ea |
1631 | #define SMB_QUERY_FS_QUOTA_INFO 0x3ee | 1641 | #define SMB_QUERY_FS_QUOTA_INFO 0x3ee |
1632 | #define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef | 1642 | #define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef |
@@ -1659,9 +1669,21 @@ typedef struct smb_com_transaction_qfsi_rsp { | |||
1659 | struct smb_hdr hdr; /* wct = 10 + SetupCount */ | 1669 | struct smb_hdr hdr; /* wct = 10 + SetupCount */ |
1660 | struct trans2_resp t2; | 1670 | struct trans2_resp t2; |
1661 | __u16 ByteCount; | 1671 | __u16 ByteCount; |
1662 | __u8 Pad; /* may be three bytes *//* followed by data area */ | 1672 | __u8 Pad; /* may be three bytes? *//* followed by data area */ |
1663 | } __attribute__((packed)) TRANSACTION2_QFSI_RSP; | 1673 | } __attribute__((packed)) TRANSACTION2_QFSI_RSP; |
1664 | 1674 | ||
1675 | typedef struct whoami_rsp_data { /* Query level 0x202 */ | ||
1676 | __u32 flags; /* 0 = Authenticated user 1 = GUEST */ | ||
1677 | __u32 mask; /* which flags bits server understands ie 0x0001 */ | ||
1678 | __u64 unix_user_id; | ||
1679 | __u64 unix_user_gid; | ||
1680 | __u32 number_of_supplementary_gids; /* may be zero */ | ||
1681 | __u32 number_of_sids; /* may be zero */ | ||
1682 | __u32 length_of_sid_array; /* in bytes - may be zero */ | ||
1683 | __u32 pad; /* reserved - MBZ */ | ||
1684 | /* __u64 gid_array[0]; */ /* may be empty */ | ||
1685 | /* __u8 * psid_list */ /* may be empty */ | ||
1686 | } __attribute__((packed)) WHOAMI_RSP_DATA; | ||
1665 | 1687 | ||
1666 | /* SETFSInfo Levels */ | 1688 | /* SETFSInfo Levels */ |
1667 | #define SMB_SET_CIFS_UNIX_INFO 0x200 | 1689 | #define SMB_SET_CIFS_UNIX_INFO 0x200 |
@@ -1858,8 +1880,11 @@ typedef struct { | |||
1858 | #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ | 1880 | #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ |
1859 | #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ | 1881 | #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ |
1860 | #define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */ | 1882 | #define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */ |
1883 | #define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based | ||
1884 | calls including posix open | ||
1885 | and posix unlink */ | ||
1861 | #ifdef CONFIG_CIFS_POSIX | 1886 | #ifdef CONFIG_CIFS_POSIX |
1862 | #define CIFS_UNIX_CAP_MASK 0x0000001b | 1887 | #define CIFS_UNIX_CAP_MASK 0x0000003b |
1863 | #else | 1888 | #else |
1864 | #define CIFS_UNIX_CAP_MASK 0x00000013 | 1889 | #define CIFS_UNIX_CAP_MASK 0x00000013 |
1865 | #endif /* CONFIG_CIFS_POSIX */ | 1890 | #endif /* CONFIG_CIFS_POSIX */ |
@@ -1946,7 +1971,7 @@ typedef struct { /* data block encoding of response to level 263 QPathInfo */ | |||
1946 | __le32 AlignmentRequirement; | 1971 | __le32 AlignmentRequirement; |
1947 | __le32 FileNameLength; | 1972 | __le32 FileNameLength; |
1948 | char FileName[1]; | 1973 | char FileName[1]; |
1949 | } __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */ | 1974 | } __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */ |
1950 | 1975 | ||
1951 | /* defines for enumerating possible values of the Unix type field below */ | 1976 | /* defines for enumerating possible values of the Unix type field below */ |
1952 | #define UNIX_FILE 0 | 1977 | #define UNIX_FILE 0 |
@@ -1970,11 +1995,11 @@ typedef struct { | |||
1970 | __u64 UniqueId; | 1995 | __u64 UniqueId; |
1971 | __le64 Permissions; | 1996 | __le64 Permissions; |
1972 | __le64 Nlinks; | 1997 | __le64 Nlinks; |
1973 | } __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */ | 1998 | } __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */ |
1974 | 1999 | ||
1975 | typedef struct { | 2000 | typedef struct { |
1976 | char LinkDest[1]; | 2001 | char LinkDest[1]; |
1977 | } __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */ | 2002 | } __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */ |
1978 | 2003 | ||
1979 | /* The following three structures are needed only for | 2004 | /* The following three structures are needed only for |
1980 | setting time to NT4 and some older servers via | 2005 | setting time to NT4 and some older servers via |
@@ -2011,7 +2036,7 @@ typedef struct { | |||
2011 | __le64 ChangeTime; | 2036 | __le64 ChangeTime; |
2012 | __le32 Attributes; | 2037 | __le32 Attributes; |
2013 | __u32 Pad; | 2038 | __u32 Pad; |
2014 | } __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */ | 2039 | } __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */ |
2015 | 2040 | ||
2016 | struct file_allocation_info { | 2041 | struct file_allocation_info { |
2017 | __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */ | 2042 | __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */ |
@@ -2020,7 +2045,7 @@ struct file_allocation_info { | |||
2020 | 2045 | ||
2021 | struct file_end_of_file_info { | 2046 | struct file_end_of_file_info { |
2022 | __le64 FileSize; /* offset to end of file */ | 2047 | __le64 FileSize; /* offset to end of file */ |
2023 | } __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */ | 2048 | } __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */ |
2024 | 2049 | ||
2025 | struct file_alt_name_info { | 2050 | struct file_alt_name_info { |
2026 | __u8 alt_name[1]; | 2051 | __u8 alt_name[1]; |
@@ -2075,6 +2100,19 @@ struct cifs_posix_acl { /* access conrol list (ACL) */ | |||
2075 | 2100 | ||
2076 | /* end of POSIX ACL definitions */ | 2101 | /* end of POSIX ACL definitions */ |
2077 | 2102 | ||
2103 | typedef struct { | ||
2104 | __u32 OpenFlags; /* same as NT CreateX */ | ||
2105 | __u32 PosixOpenFlags; | ||
2106 | __u32 Mode; | ||
2107 | __u16 Level; /* reply level requested (see QPathInfo levels) */ | ||
2108 | __u16 Pad; /* reserved - MBZ */ | ||
2109 | } __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */ | ||
2110 | |||
2111 | typedef struct { | ||
2112 | /* reply varies based on requested level */ | ||
2113 | } __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */ | ||
2114 | |||
2115 | |||
2078 | struct file_internal_info { | 2116 | struct file_internal_info { |
2079 | __u64 UniqueId; /* inode number */ | 2117 | __u64 UniqueId; /* inode number */ |
2080 | } __attribute__((packed)); /* level 0x3ee */ | 2118 | } __attribute__((packed)); /* level 0x3ee */ |
@@ -2238,7 +2276,8 @@ struct data_blob { | |||
2238 | 1) PosixCreateX - to set and return the mode, inode#, device info and | 2276 | 1) PosixCreateX - to set and return the mode, inode#, device info and |
2239 | perhaps add a CreateDevice - to create Pipes and other special .inodes | 2277 | perhaps add a CreateDevice - to create Pipes and other special .inodes |
2240 | Also note POSIX open flags | 2278 | Also note POSIX open flags |
2241 | 2) Close - to return the last write time to do cache across close more safely | 2279 | 2) Close - to return the last write time to do cache across close |
2280 | more safely | ||
2242 | 3) FindFirst return unique inode number - what about resume key, two | 2281 | 3) FindFirst return unique inode number - what about resume key, two |
2243 | forms short (matches readdir) and full (enough info to cache inodes) | 2282 | forms short (matches readdir) and full (enough info to cache inodes) |
2244 | 4) Mkdir - set mode | 2283 | 4) Mkdir - set mode |
@@ -2273,7 +2312,8 @@ struct data_blob { | |||
2273 | TRANSACTION2 (18 cases) | 2312 | TRANSACTION2 (18 cases) |
2274 | SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2 | 2313 | SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2 |
2275 | (BB verify that never need to set allocation size) | 2314 | (BB verify that never need to set allocation size) |
2276 | SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?) | 2315 | SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via |
2316 | Unix ext?) | ||
2277 | 2317 | ||
2278 | COPY (note support for copy across directories) - FUTURE, OPTIONAL | 2318 | COPY (note support for copy across directories) - FUTURE, OPTIONAL |
2279 | setting/getting OS/2 EAs - FUTURE (BB can this handle | 2319 | setting/getting OS/2 EAs - FUTURE (BB can this handle |
@@ -2293,13 +2333,13 @@ struct data_blob { | |||
2293 | T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields | 2333 | T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields |
2294 | Actually need QUERY_FILE_UNIX_INFO since has inode num | 2334 | Actually need QUERY_FILE_UNIX_INFO since has inode num |
2295 | BB what about a) blksize/blkbits/blocks | 2335 | BB what about a) blksize/blkbits/blocks |
2296 | b) i_version | 2336 | b) i_version |
2297 | c) i_rdev | 2337 | c) i_rdev |
2298 | d) notify mask? | 2338 | d) notify mask? |
2299 | e) generation | 2339 | e) generation |
2300 | f) size_seqcount | 2340 | f) size_seqcount |
2301 | T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX | 2341 | T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX |
2302 | TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended | 2342 | TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended |
2303 | T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL | 2343 | T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL |
2304 | 2344 | ||
2305 | 2345 | ||
@@ -2338,7 +2378,7 @@ typedef struct file_xattr_info { | |||
2338 | __u32 xattr_value_len; | 2378 | __u32 xattr_value_len; |
2339 | char xattr_name[0]; | 2379 | char xattr_name[0]; |
2340 | /* followed by xattr_value[xattr_value_len], no pad */ | 2380 | /* followed by xattr_value[xattr_value_len], no pad */ |
2341 | } __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */ | 2381 | } __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */ |
2342 | 2382 | ||
2343 | 2383 | ||
2344 | /* flags for chattr command */ | 2384 | /* flags for chattr command */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index f1f8225102f0..6148b82170c4 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/nls.h> | 23 | #include <linux/nls.h> |
24 | 24 | ||
25 | struct statfs; | 25 | struct statfs; |
26 | struct smb_vol; | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | ***************************************************************** | 29 | ***************************************************************** |
@@ -57,7 +58,7 @@ extern int SendReceiveBlockingLock(const unsigned int /* xid */ , | |||
57 | int * /* bytes returned */); | 58 | int * /* bytes returned */); |
58 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); | 59 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); |
59 | extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); | 60 | extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); |
60 | extern int is_size_safe_to_change(struct cifsInodeInfo *); | 61 | extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); |
61 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); | 62 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); |
62 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); | 63 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); |
63 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | 64 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); |
@@ -147,6 +148,8 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | |||
147 | unsigned int *pnum_referrals, | 148 | unsigned int *pnum_referrals, |
148 | unsigned char ** preferrals, | 149 | unsigned char ** preferrals, |
149 | int remap); | 150 | int remap); |
151 | extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, | ||
152 | struct super_block * sb, struct smb_vol * vol); | ||
150 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, | 153 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, |
151 | struct kstatfs *FSData); | 154 | struct kstatfs *FSData); |
152 | extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, | 155 | extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 472e33e0f3cf..24364106b8f9 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -158,9 +158,15 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
158 | nls_codepage); | 158 | nls_codepage); |
159 | if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { | 159 | if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { |
160 | mark_open_files_invalid(tcon); | 160 | mark_open_files_invalid(tcon); |
161 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon | 161 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, |
162 | , nls_codepage); | 162 | tcon, nls_codepage); |
163 | up(&tcon->ses->sesSem); | 163 | up(&tcon->ses->sesSem); |
164 | /* tell server which Unix caps we support */ | ||
165 | if (tcon->ses->capabilities & CAP_UNIX) | ||
166 | reset_cifs_unix_caps(0 /* no xid */, | ||
167 | tcon, | ||
168 | NULL /* we do not know sb */, | ||
169 | NULL /* no vol info */); | ||
164 | /* BB FIXME add code to check if wsize needs | 170 | /* BB FIXME add code to check if wsize needs |
165 | update due to negotiated smb buffer size | 171 | update due to negotiated smb buffer size |
166 | shrinking */ | 172 | shrinking */ |
@@ -298,6 +304,12 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
298 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, | 304 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, |
299 | tcon, nls_codepage); | 305 | tcon, nls_codepage); |
300 | up(&tcon->ses->sesSem); | 306 | up(&tcon->ses->sesSem); |
307 | /* tell server which Unix caps we support */ | ||
308 | if (tcon->ses->capabilities & CAP_UNIX) | ||
309 | reset_cifs_unix_caps(0 /* no xid */, | ||
310 | tcon, | ||
311 | NULL /* do not know sb */, | ||
312 | NULL /* no vol info */); | ||
301 | /* BB FIXME add code to check if wsize needs | 313 | /* BB FIXME add code to check if wsize needs |
302 | update due to negotiated smb buffer size | 314 | update due to negotiated smb buffer size |
303 | shrinking */ | 315 | shrinking */ |
@@ -2812,10 +2824,10 @@ GetExtAttrOut: | |||
2812 | 2824 | ||
2813 | 2825 | ||
2814 | /* security id for everyone */ | 2826 | /* security id for everyone */ |
2815 | const static struct cifs_sid sid_everyone = | 2827 | static const struct cifs_sid sid_everyone = |
2816 | {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; | 2828 | {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; |
2817 | /* group users */ | 2829 | /* group users */ |
2818 | const static struct cifs_sid sid_user = | 2830 | static const struct cifs_sid sid_user = |
2819 | {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; | 2831 | {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; |
2820 | 2832 | ||
2821 | /* Convert CIFS ACL to POSIX form */ | 2833 | /* Convert CIFS ACL to POSIX form */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2caca06b4bae..20ba7dcc9959 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1613,6 +1613,76 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
1613 | return rc; | 1613 | return rc; |
1614 | } | 1614 | } |
1615 | 1615 | ||
1616 | void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon, | ||
1617 | struct super_block * sb, struct smb_vol * vol_info) | ||
1618 | { | ||
1619 | /* if we are reconnecting then should we check to see if | ||
1620 | * any requested capabilities changed locally e.g. via | ||
1621 | * remount but we can not do much about it here | ||
1622 | * if they have (even if we could detect it by the following) | ||
1623 | * Perhaps we could add a backpointer to array of sb from tcon | ||
1624 | * or if we change to make all sb to same share the same | ||
1625 | * sb as NFS - then we only have one backpointer to sb. | ||
1626 | * What if we wanted to mount the server share twice once with | ||
1627 | * and once without posixacls or posix paths? */ | ||
1628 | __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); | ||
1629 | |||
1630 | |||
1631 | if(!CIFSSMBQFSUnixInfo(xid, tcon)) { | ||
1632 | __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability); | ||
1633 | |||
1634 | /* check for reconnect case in which we do not | ||
1635 | want to change the mount behavior if we can avoid it */ | ||
1636 | if(vol_info == NULL) { | ||
1637 | /* turn off POSIX ACL and PATHNAMES if not set | ||
1638 | originally at mount time */ | ||
1639 | if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0) | ||
1640 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; | ||
1641 | if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) | ||
1642 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; | ||
1643 | |||
1644 | |||
1645 | |||
1646 | |||
1647 | } | ||
1648 | |||
1649 | cap &= CIFS_UNIX_CAP_MASK; | ||
1650 | if(vol_info && vol_info->no_psx_acl) | ||
1651 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; | ||
1652 | else if(CIFS_UNIX_POSIX_ACL_CAP & cap) { | ||
1653 | cFYI(1,("negotiated posix acl support")); | ||
1654 | if(sb) | ||
1655 | sb->s_flags |= MS_POSIXACL; | ||
1656 | } | ||
1657 | |||
1658 | if(vol_info && vol_info->posix_paths == 0) | ||
1659 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; | ||
1660 | else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { | ||
1661 | cFYI(1,("negotiate posix pathnames")); | ||
1662 | if(sb) | ||
1663 | CIFS_SB(sb)->mnt_cifs_flags |= | ||
1664 | CIFS_MOUNT_POSIX_PATHS; | ||
1665 | } | ||
1666 | |||
1667 | cFYI(1,("Negotiate caps 0x%x",(int)cap)); | ||
1668 | #ifdef CONFIG_CIFS_DEBUG2 | ||
1669 | if(cap & CIFS_UNIX_FCNTL_CAP) | ||
1670 | cFYI(1,("FCNTL cap")); | ||
1671 | if(cap & CIFS_UNIX_EXTATTR_CAP) | ||
1672 | cFYI(1,("EXTATTR cap")); | ||
1673 | if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) | ||
1674 | cFYI(1,("POSIX path cap")); | ||
1675 | if(cap & CIFS_UNIX_XATTR_CAP) | ||
1676 | cFYI(1,("XATTR cap")); | ||
1677 | if(cap & CIFS_UNIX_POSIX_ACL_CAP) | ||
1678 | cFYI(1,("POSIX ACL cap")); | ||
1679 | #endif /* CIFS_DEBUG2 */ | ||
1680 | if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { | ||
1681 | cFYI(1,("setting capabilities failed")); | ||
1682 | } | ||
1683 | } | ||
1684 | } | ||
1685 | |||
1616 | int | 1686 | int |
1617 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 1687 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, |
1618 | char *mount_data, const char *devname) | 1688 | char *mount_data, const char *devname) |
@@ -1928,20 +1998,25 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1928 | if (tcon == NULL) | 1998 | if (tcon == NULL) |
1929 | rc = -ENOMEM; | 1999 | rc = -ENOMEM; |
1930 | else { | 2000 | else { |
1931 | /* check for null share name ie connect to dfs root */ | 2001 | /* check for null share name ie connecting to |
2002 | * dfs root */ | ||
1932 | 2003 | ||
1933 | /* BB check if this works for exactly length three strings */ | 2004 | /* BB check if this works for exactly length |
2005 | * three strings */ | ||
1934 | if ((strchr(volume_info.UNC + 3, '\\') == NULL) | 2006 | if ((strchr(volume_info.UNC + 3, '\\') == NULL) |
1935 | && (strchr(volume_info.UNC + 3, '/') == | 2007 | && (strchr(volume_info.UNC + 3, '/') == |
1936 | NULL)) { | 2008 | NULL)) { |
1937 | rc = connect_to_dfs_path(xid, pSesInfo, | 2009 | rc = connect_to_dfs_path(xid, pSesInfo, |
1938 | "", cifs_sb->local_nls, | 2010 | "", cifs_sb->local_nls, |
1939 | cifs_sb->mnt_cifs_flags & | 2011 | cifs_sb->mnt_cifs_flags & |
1940 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 2012 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1941 | kfree(volume_info.UNC); | 2013 | kfree(volume_info.UNC); |
1942 | FreeXid(xid); | 2014 | FreeXid(xid); |
1943 | return -ENODEV; | 2015 | return -ENODEV; |
1944 | } else { | 2016 | } else { |
2017 | /* BB Do we need to wrap sesSem around | ||
2018 | * this TCon call and Unix SetFS as | ||
2019 | * we do on SessSetup and reconnect? */ | ||
1945 | rc = CIFSTCon(xid, pSesInfo, | 2020 | rc = CIFSTCon(xid, pSesInfo, |
1946 | volume_info.UNC, | 2021 | volume_info.UNC, |
1947 | tcon, cifs_sb->local_nls); | 2022 | tcon, cifs_sb->local_nls); |
@@ -1962,6 +2037,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1962 | sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ | 2037 | sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ |
1963 | } | 2038 | } |
1964 | 2039 | ||
2040 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ | ||
1965 | sb->s_time_gran = 100; | 2041 | sb->s_time_gran = 100; |
1966 | 2042 | ||
1967 | /* on error free sesinfo and tcon struct if needed */ | 2043 | /* on error free sesinfo and tcon struct if needed */ |
@@ -2006,45 +2082,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2006 | /* do not care if following two calls succeed - informational */ | 2082 | /* do not care if following two calls succeed - informational */ |
2007 | CIFSSMBQFSDeviceInfo(xid, tcon); | 2083 | CIFSSMBQFSDeviceInfo(xid, tcon); |
2008 | CIFSSMBQFSAttributeInfo(xid, tcon); | 2084 | CIFSSMBQFSAttributeInfo(xid, tcon); |
2009 | 2085 | ||
2010 | if (tcon->ses->capabilities & CAP_UNIX) { | 2086 | /* tell server which Unix caps we support */ |
2011 | if(!CIFSSMBQFSUnixInfo(xid, tcon)) { | 2087 | if (tcon->ses->capabilities & CAP_UNIX) |
2012 | __u64 cap = | 2088 | reset_cifs_unix_caps(xid, tcon, sb, &volume_info); |
2013 | le64_to_cpu(tcon->fsUnixInfo.Capability); | 2089 | |
2014 | cap &= CIFS_UNIX_CAP_MASK; | ||
2015 | if(volume_info.no_psx_acl) | ||
2016 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; | ||
2017 | else if(CIFS_UNIX_POSIX_ACL_CAP & cap) { | ||
2018 | cFYI(1,("negotiated posix acl support")); | ||
2019 | sb->s_flags |= MS_POSIXACL; | ||
2020 | } | ||
2021 | |||
2022 | if(volume_info.posix_paths == 0) | ||
2023 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; | ||
2024 | else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { | ||
2025 | cFYI(1,("negotiate posix pathnames")); | ||
2026 | cifs_sb->mnt_cifs_flags |= | ||
2027 | CIFS_MOUNT_POSIX_PATHS; | ||
2028 | } | ||
2029 | |||
2030 | cFYI(1,("Negotiate caps 0x%x",(int)cap)); | ||
2031 | #ifdef CONFIG_CIFS_DEBUG2 | ||
2032 | if(cap & CIFS_UNIX_FCNTL_CAP) | ||
2033 | cFYI(1,("FCNTL cap")); | ||
2034 | if(cap & CIFS_UNIX_EXTATTR_CAP) | ||
2035 | cFYI(1,("EXTATTR cap")); | ||
2036 | if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) | ||
2037 | cFYI(1,("POSIX path cap")); | ||
2038 | if(cap & CIFS_UNIX_XATTR_CAP) | ||
2039 | cFYI(1,("XATTR cap")); | ||
2040 | if(cap & CIFS_UNIX_POSIX_ACL_CAP) | ||
2041 | cFYI(1,("POSIX ACL cap")); | ||
2042 | #endif /* CIFS_DEBUG2 */ | ||
2043 | if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { | ||
2044 | cFYI(1,("setting capabilities failed")); | ||
2045 | } | ||
2046 | } | ||
2047 | } | ||
2048 | if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) | 2090 | if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) |
2049 | cifs_sb->wsize = min(cifs_sb->wsize, | 2091 | cifs_sb->wsize = min(cifs_sb->wsize, |
2050 | (tcon->ses->server->maxBuf - | 2092 | (tcon->ses->server->maxBuf - |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e9dcf5ee29a2..a1265c9bfec0 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1014,8 +1014,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1014 | /* since the write may have blocked check these pointers again */ | 1014 | /* since the write may have blocked check these pointers again */ |
1015 | if (file->f_path.dentry) { | 1015 | if (file->f_path.dentry) { |
1016 | if (file->f_path.dentry->d_inode) { | 1016 | if (file->f_path.dentry->d_inode) { |
1017 | file->f_path.dentry->d_inode->i_ctime = | 1017 | /*BB We could make this contingent on superblock ATIME flag too */ |
1018 | file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME; | 1018 | /* file->f_path.dentry->d_inode->i_ctime = |
1019 | file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/ | ||
1019 | if (total_written > 0) { | 1020 | if (total_written > 0) { |
1020 | if (*poffset > file->f_path.dentry->d_inode->i_size) | 1021 | if (*poffset > file->f_path.dentry->d_inode->i_size) |
1021 | i_size_write(file->f_path.dentry->d_inode, | 1022 | i_size_write(file->f_path.dentry->d_inode, |
@@ -1954,7 +1955,7 @@ static int cifs_readpage(struct file *file, struct page *page) | |||
1954 | refreshing the inode only on increases in the file size | 1955 | refreshing the inode only on increases in the file size |
1955 | but this is tricky to do without racing with writebehind | 1956 | but this is tricky to do without racing with writebehind |
1956 | page caching in the current Linux kernel design */ | 1957 | page caching in the current Linux kernel design */ |
1957 | int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) | 1958 | int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file) |
1958 | { | 1959 | { |
1959 | struct cifsFileInfo *open_file = NULL; | 1960 | struct cifsFileInfo *open_file = NULL; |
1960 | 1961 | ||
@@ -1976,6 +1977,9 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) | |||
1976 | return 1; | 1977 | return 1; |
1977 | } | 1978 | } |
1978 | 1979 | ||
1980 | if(i_size_read(&cifsInode->vfs_inode) < end_of_file) | ||
1981 | return 1; | ||
1982 | |||
1979 | return 0; | 1983 | return 0; |
1980 | } else | 1984 | } else |
1981 | return 1; | 1985 | return 1; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index c4fa91b8b62f..37c6ce87416b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -90,6 +90,9 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
90 | (*pinode)->i_ino = | 90 | (*pinode)->i_ino = |
91 | (unsigned long)findData.UniqueId; | 91 | (unsigned long)findData.UniqueId; |
92 | } /* note ino incremented to unique num in new_inode */ | 92 | } /* note ino incremented to unique num in new_inode */ |
93 | if(sb->s_flags & MS_NOATIME) | ||
94 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; | ||
95 | |||
93 | insert_inode_hash(*pinode); | 96 | insert_inode_hash(*pinode); |
94 | } | 97 | } |
95 | 98 | ||
@@ -140,7 +143,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
140 | inode->i_gid = le64_to_cpu(findData.Gid); | 143 | inode->i_gid = le64_to_cpu(findData.Gid); |
141 | inode->i_nlink = le64_to_cpu(findData.Nlinks); | 144 | inode->i_nlink = le64_to_cpu(findData.Nlinks); |
142 | 145 | ||
143 | if (is_size_safe_to_change(cifsInfo)) { | 146 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { |
144 | /* can not safely change the file size here if the | 147 | /* can not safely change the file size here if the |
145 | client is writing to it due to potential races */ | 148 | client is writing to it due to potential races */ |
146 | 149 | ||
@@ -421,6 +424,8 @@ int cifs_get_inode_info(struct inode **pinode, | |||
421 | } else /* do we need cast or hash to ino? */ | 424 | } else /* do we need cast or hash to ino? */ |
422 | (*pinode)->i_ino = inode_num; | 425 | (*pinode)->i_ino = inode_num; |
423 | } /* else ino incremented to unique num in new_inode*/ | 426 | } /* else ino incremented to unique num in new_inode*/ |
427 | if(sb->s_flags & MS_NOATIME) | ||
428 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; | ||
424 | insert_inode_hash(*pinode); | 429 | insert_inode_hash(*pinode); |
425 | } | 430 | } |
426 | inode = *pinode; | 431 | inode = *pinode; |
@@ -491,8 +496,8 @@ int cifs_get_inode_info(struct inode **pinode, | |||
491 | /* BB add code here - | 496 | /* BB add code here - |
492 | validate if device or weird share or device type? */ | 497 | validate if device or weird share or device type? */ |
493 | } | 498 | } |
494 | if (is_size_safe_to_change(cifsInfo)) { | 499 | if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) { |
495 | /* can not safely change the file size here if the | 500 | /* can not safely shrink the file size here if the |
496 | client is writing to it due to potential races */ | 501 | client is writing to it due to potential races */ |
497 | i_size_write(inode,le64_to_cpu(pfindData->EndOfFile)); | 502 | i_size_write(inode,le64_to_cpu(pfindData->EndOfFile)); |
498 | 503 | ||
@@ -1359,7 +1364,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1359 | and this check ensures that we are not being called from | 1364 | and this check ensures that we are not being called from |
1360 | sys_utimes in which case we ought to fail the call back to | 1365 | sys_utimes in which case we ought to fail the call back to |
1361 | the user when the server rejects the call */ | 1366 | the user when the server rejects the call */ |
1362 | if((rc) && (attrs->ia_valid && | 1367 | if((rc) && (attrs->ia_valid & |
1363 | (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) | 1368 | (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) |
1364 | rc = 0; | 1369 | rc = 0; |
1365 | } | 1370 | } |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 8e259969354b..6baea85d726e 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -77,7 +77,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, | |||
77 | cifsInode = CIFS_I(old_file->d_inode); | 77 | cifsInode = CIFS_I(old_file->d_inode); |
78 | if(rc == 0) { | 78 | if(rc == 0) { |
79 | old_file->d_inode->i_nlink++; | 79 | old_file->d_inode->i_nlink++; |
80 | old_file->d_inode->i_ctime = CURRENT_TIME; | 80 | /* BB should we make this contingent on superblock flag NOATIME? */ |
81 | /* old_file->d_inode->i_ctime = CURRENT_TIME;*/ | ||
81 | /* parent dir timestamps will update from srv | 82 | /* parent dir timestamps will update from srv |
82 | within a second, would it really be worth it | 83 | within a second, would it really be worth it |
83 | to set the parent dir cifs inode time to zero | 84 | to set the parent dir cifs inode time to zero |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 782940be550f..c444798f0740 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -83,6 +83,8 @@ static int construct_dentry(struct qstr *qstring, struct file *file, | |||
83 | return rc; | 83 | return rc; |
84 | rc = 1; | 84 | rc = 1; |
85 | } | 85 | } |
86 | if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME) | ||
87 | (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; | ||
86 | } else { | 88 | } else { |
87 | tmp_dentry = d_alloc(file->f_path.dentry, qstring); | 89 | tmp_dentry = d_alloc(file->f_path.dentry, qstring); |
88 | if(tmp_dentry == NULL) { | 90 | if(tmp_dentry == NULL) { |
@@ -98,6 +100,8 @@ static int construct_dentry(struct qstr *qstring, struct file *file, | |||
98 | tmp_dentry->d_op = &cifs_dentry_ops; | 100 | tmp_dentry->d_op = &cifs_dentry_ops; |
99 | if(*ptmp_inode == NULL) | 101 | if(*ptmp_inode == NULL) |
100 | return rc; | 102 | return rc; |
103 | if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME) | ||
104 | (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; | ||
101 | rc = 2; | 105 | rc = 2; |
102 | } | 106 | } |
103 | 107 | ||
@@ -222,7 +226,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
222 | atomic_set(&cifsInfo->inUse, 1); | 226 | atomic_set(&cifsInfo->inUse, 1); |
223 | } | 227 | } |
224 | 228 | ||
225 | if (is_size_safe_to_change(cifsInfo)) { | 229 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { |
226 | /* can not safely change the file size here if the | 230 | /* can not safely change the file size here if the |
227 | client is writing to it due to potential races */ | 231 | client is writing to it due to potential races */ |
228 | i_size_write(tmp_inode, end_of_file); | 232 | i_size_write(tmp_inode, end_of_file); |
@@ -351,10 +355,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode, | |||
351 | tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); | 355 | tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); |
352 | tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); | 356 | tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); |
353 | 357 | ||
354 | if (is_size_safe_to_change(cifsInfo)) { | 358 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { |
355 | /* can not safely change the file size here if the | 359 | /* can not safely change the file size here if the |
356 | client is writing to it due to potential races */ | 360 | client is writing to it due to potential races */ |
357 | i_size_write(tmp_inode,end_of_file); | 361 | i_size_write(tmp_inode, end_of_file); |
358 | 362 | ||
359 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | 363 | /* 512 bytes (2**9) is the fake blocksize that must be used */ |
360 | /* for this calculation, not the real blocksize */ | 364 | /* for this calculation, not the real blocksize */ |
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 4c9fecbfa91f..28c872747f81 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c | |||
@@ -16,7 +16,7 @@ static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) | |||
16 | return memcmp(fid1, fid2, sizeof(*fid1)) == 0; | 16 | return memcmp(fid1, fid2, sizeof(*fid1)) == 0; |
17 | } | 17 | } |
18 | 18 | ||
19 | static struct inode_operations coda_symlink_inode_operations = { | 19 | static const struct inode_operations coda_symlink_inode_operations = { |
20 | .readlink = generic_readlink, | 20 | .readlink = generic_readlink, |
21 | .follow_link = page_follow_link_light, | 21 | .follow_link = page_follow_link_light, |
22 | .put_link = page_put_link, | 22 | .put_link = page_put_link, |
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 0c6f7f3b3dd7..9ddf5ed62162 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
@@ -66,7 +66,7 @@ static struct dentry_operations coda_dentry_operations = | |||
66 | .d_delete = coda_dentry_delete, | 66 | .d_delete = coda_dentry_delete, |
67 | }; | 67 | }; |
68 | 68 | ||
69 | struct inode_operations coda_dir_inode_operations = | 69 | const struct inode_operations coda_dir_inode_operations = |
70 | { | 70 | { |
71 | .create = coda_create, | 71 | .create = coda_create, |
72 | .lookup = coda_lookup, | 72 | .lookup = coda_lookup, |
diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 01395defed85..614175a3b02e 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c | |||
@@ -90,7 +90,7 @@ static int coda_remount(struct super_block *sb, int *flags, char *data) | |||
90 | } | 90 | } |
91 | 91 | ||
92 | /* exported operations */ | 92 | /* exported operations */ |
93 | static struct super_operations coda_super_operations = | 93 | static const struct super_operations coda_super_operations = |
94 | { | 94 | { |
95 | .alloc_inode = coda_alloc_inode, | 95 | .alloc_inode = coda_alloc_inode, |
96 | .destroy_inode = coda_destroy_inode, | 96 | .destroy_inode = coda_destroy_inode, |
@@ -271,7 +271,7 @@ int coda_setattr(struct dentry *de, struct iattr *iattr) | |||
271 | return error; | 271 | return error; |
272 | } | 272 | } |
273 | 273 | ||
274 | struct inode_operations coda_file_inode_operations = { | 274 | const struct inode_operations coda_file_inode_operations = { |
275 | .permission = coda_permission, | 275 | .permission = coda_permission, |
276 | .getattr = coda_getattr, | 276 | .getattr = coda_getattr, |
277 | .setattr = coda_setattr, | 277 | .setattr = coda_setattr, |
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 214822be87bd..2bf3026adc80 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c | |||
@@ -30,7 +30,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp, | |||
30 | unsigned int cmd, unsigned long user_data); | 30 | unsigned int cmd, unsigned long user_data); |
31 | 31 | ||
32 | /* exported from this file */ | 32 | /* exported from this file */ |
33 | struct inode_operations coda_ioctl_inode_operations = | 33 | const struct inode_operations coda_ioctl_inode_operations = |
34 | { | 34 | { |
35 | .permission = coda_ioctl_permission, | 35 | .permission = coda_ioctl_permission, |
36 | .setattr = coda_setattr, | 36 | .setattr = coda_setattr, |
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index 1c82e9a7d7c8..c57a1fa7cf23 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
16 | #include <linux/sysctl.h> | 16 | #include <linux/sysctl.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/seq_file.h> | ||
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
19 | #include <linux/stat.h> | 20 | #include <linux/stat.h> |
20 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
@@ -32,8 +33,6 @@ | |||
32 | 33 | ||
33 | static struct ctl_table_header *fs_table_header; | 34 | static struct ctl_table_header *fs_table_header; |
34 | 35 | ||
35 | #define FS_CODA 1 /* Coda file system */ | ||
36 | |||
37 | #define CODA_TIMEOUT 3 /* timeout on upcalls to become intrble */ | 36 | #define CODA_TIMEOUT 3 /* timeout on upcalls to become intrble */ |
38 | #define CODA_HARD 5 /* mount type "hard" or "soft" */ | 37 | #define CODA_HARD 5 /* mount type "hard" or "soft" */ |
39 | #define CODA_VFS 6 /* vfs statistics */ | 38 | #define CODA_VFS 6 /* vfs statistics */ |
@@ -84,15 +83,11 @@ static int do_reset_coda_cache_inv_stats( ctl_table * table, int write, | |||
84 | return 0; | 83 | return 0; |
85 | } | 84 | } |
86 | 85 | ||
87 | static int coda_vfs_stats_get_info( char * buffer, char ** start, | 86 | static int proc_vfs_stats_show(struct seq_file *m, void *v) |
88 | off_t offset, int length) | ||
89 | { | 87 | { |
90 | int len=0; | ||
91 | off_t begin; | ||
92 | struct coda_vfs_stats * ps = & coda_vfs_stat; | 88 | struct coda_vfs_stats * ps = & coda_vfs_stat; |
93 | 89 | ||
94 | /* this works as long as we are below 1024 characters! */ | 90 | seq_printf(m, |
95 | len += sprintf( buffer, | ||
96 | "Coda VFS statistics\n" | 91 | "Coda VFS statistics\n" |
97 | "===================\n\n" | 92 | "===================\n\n" |
98 | "File Operations:\n" | 93 | "File Operations:\n" |
@@ -132,28 +127,14 @@ static int coda_vfs_stats_get_info( char * buffer, char ** start, | |||
132 | ps->rmdir, | 127 | ps->rmdir, |
133 | ps->rename, | 128 | ps->rename, |
134 | ps->permission); | 129 | ps->permission); |
135 | 130 | return 0; | |
136 | begin = offset; | ||
137 | *start = buffer + begin; | ||
138 | len -= begin; | ||
139 | |||
140 | if ( len > length ) | ||
141 | len = length; | ||
142 | if ( len < 0 ) | ||
143 | len = 0; | ||
144 | |||
145 | return len; | ||
146 | } | 131 | } |
147 | 132 | ||
148 | static int coda_cache_inv_stats_get_info( char * buffer, char ** start, | 133 | static int proc_cache_inv_stats_show(struct seq_file *m, void *v) |
149 | off_t offset, int length) | ||
150 | { | 134 | { |
151 | int len=0; | ||
152 | off_t begin; | ||
153 | struct coda_cache_inv_stats * ps = & coda_cache_inv_stat; | 135 | struct coda_cache_inv_stats * ps = & coda_cache_inv_stat; |
154 | 136 | ||
155 | /* this works as long as we are below 1024 characters! */ | 137 | seq_printf(m, |
156 | len += sprintf( buffer, | ||
157 | "Coda cache invalidation statistics\n" | 138 | "Coda cache invalidation statistics\n" |
158 | "==================================\n\n" | 139 | "==================================\n\n" |
159 | "flush\t\t%9d\n" | 140 | "flush\t\t%9d\n" |
@@ -170,31 +151,87 @@ static int coda_cache_inv_stats_get_info( char * buffer, char ** start, | |||
170 | ps->zap_vnode, | 151 | ps->zap_vnode, |
171 | ps->purge_fid, | 152 | ps->purge_fid, |
172 | ps->replace ); | 153 | ps->replace ); |
173 | 154 | return 0; | |
174 | begin = offset; | 155 | } |
175 | *start = buffer + begin; | ||
176 | len -= begin; | ||
177 | 156 | ||
178 | if ( len > length ) | 157 | static int proc_vfs_stats_open(struct inode *inode, struct file *file) |
179 | len = length; | 158 | { |
180 | if ( len < 0 ) | 159 | return single_open(file, proc_vfs_stats_show, NULL); |
181 | len = 0; | 160 | } |
182 | 161 | ||
183 | return len; | 162 | static int proc_cache_inv_stats_open(struct inode *inode, struct file *file) |
163 | { | ||
164 | return single_open(file, proc_cache_inv_stats_show, NULL); | ||
184 | } | 165 | } |
185 | 166 | ||
167 | static const struct file_operations proc_vfs_stats_fops = { | ||
168 | .owner = THIS_MODULE, | ||
169 | .open = proc_vfs_stats_open, | ||
170 | .read = seq_read, | ||
171 | .llseek = seq_lseek, | ||
172 | .release = single_release, | ||
173 | }; | ||
174 | |||
175 | static const struct file_operations proc_cache_inv_stats_fops = { | ||
176 | .owner = THIS_MODULE, | ||
177 | .open = proc_cache_inv_stats_open, | ||
178 | .read = seq_read, | ||
179 | .llseek = seq_lseek, | ||
180 | .release = single_release, | ||
181 | }; | ||
182 | |||
186 | static ctl_table coda_table[] = { | 183 | static ctl_table coda_table[] = { |
187 | {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, | 184 | { |
188 | {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec}, | 185 | .ctl_name = CTL_UNNUMBERED, |
189 | {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats}, | 186 | .procname = "timeout", |
190 | {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats}, | 187 | .data = &coda_timeout, |
191 | {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec}, | 188 | .maxlen = sizeof(int), |
192 | { 0 } | 189 | .mode = 0644, |
190 | .proc_handler = &proc_dointvec | ||
191 | }, | ||
192 | { | ||
193 | .ctl_name = CTL_UNNUMBERED, | ||
194 | .procname = "hard", | ||
195 | .data = &coda_hard, | ||
196 | .maxlen = sizeof(int), | ||
197 | .mode = 0644, | ||
198 | .proc_handler = &proc_dointvec | ||
199 | }, | ||
200 | { | ||
201 | .ctl_name = CTL_UNNUMBERED, | ||
202 | .procname = "vfs_stats", | ||
203 | .data = NULL, | ||
204 | .maxlen = 0, | ||
205 | .mode = 0644, | ||
206 | .proc_handler = &do_reset_coda_vfs_stats | ||
207 | }, | ||
208 | { | ||
209 | .ctl_name = CTL_UNNUMBERED, | ||
210 | .procname = "cache_inv_stats", | ||
211 | .data = NULL, | ||
212 | .maxlen = 0, | ||
213 | .mode = 0644, | ||
214 | .proc_handler = &do_reset_coda_cache_inv_stats | ||
215 | }, | ||
216 | { | ||
217 | .ctl_name = CTL_UNNUMBERED, | ||
218 | .procname = "fake_statfs", | ||
219 | .data = &coda_fake_statfs, | ||
220 | .maxlen = sizeof(int), | ||
221 | .mode = 0600, | ||
222 | .proc_handler = &proc_dointvec | ||
223 | }, | ||
224 | {} | ||
193 | }; | 225 | }; |
194 | 226 | ||
195 | static ctl_table fs_table[] = { | 227 | static ctl_table fs_table[] = { |
196 | {FS_CODA, "coda", NULL, 0, 0555, coda_table}, | 228 | { |
197 | {0} | 229 | .ctl_name = CTL_UNNUMBERED, |
230 | .procname = "coda", | ||
231 | .mode = 0555, | ||
232 | .child = coda_table | ||
233 | }, | ||
234 | {} | ||
198 | }; | 235 | }; |
199 | 236 | ||
200 | 237 | ||
@@ -212,9 +249,6 @@ static struct proc_dir_entry* proc_fs_coda; | |||
212 | 249 | ||
213 | #endif | 250 | #endif |
214 | 251 | ||
215 | #define coda_proc_create(name,get_info) \ | ||
216 | create_proc_info_entry(name, 0, proc_fs_coda, get_info) | ||
217 | |||
218 | void coda_sysctl_init(void) | 252 | void coda_sysctl_init(void) |
219 | { | 253 | { |
220 | reset_coda_vfs_stats(); | 254 | reset_coda_vfs_stats(); |
@@ -223,15 +257,21 @@ void coda_sysctl_init(void) | |||
223 | #ifdef CONFIG_PROC_FS | 257 | #ifdef CONFIG_PROC_FS |
224 | proc_fs_coda = proc_mkdir("coda", proc_root_fs); | 258 | proc_fs_coda = proc_mkdir("coda", proc_root_fs); |
225 | if (proc_fs_coda) { | 259 | if (proc_fs_coda) { |
260 | struct proc_dir_entry *pde; | ||
261 | |||
226 | proc_fs_coda->owner = THIS_MODULE; | 262 | proc_fs_coda->owner = THIS_MODULE; |
227 | coda_proc_create("vfs_stats", coda_vfs_stats_get_info); | 263 | pde = create_proc_entry("vfs_stats", 0, proc_fs_coda); |
228 | coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info); | 264 | if (pde) |
265 | pde->proc_fops = &proc_vfs_stats_fops; | ||
266 | pde = create_proc_entry("cache_inv_stats", 0, proc_fs_coda); | ||
267 | if (pde) | ||
268 | pde->proc_fops = &proc_cache_inv_stats_fops; | ||
229 | } | 269 | } |
230 | #endif | 270 | #endif |
231 | 271 | ||
232 | #ifdef CONFIG_SYSCTL | 272 | #ifdef CONFIG_SYSCTL |
233 | if ( !fs_table_header ) | 273 | if ( !fs_table_header ) |
234 | fs_table_header = register_sysctl_table(fs_table, 0); | 274 | fs_table_header = register_sysctl_table(fs_table); |
235 | #endif | 275 | #endif |
236 | } | 276 | } |
237 | 277 | ||
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index f92cd303d2c9..7b48c034b312 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h | |||
@@ -75,8 +75,8 @@ extern struct super_block * configfs_sb; | |||
75 | extern const struct file_operations configfs_dir_operations; | 75 | extern const struct file_operations configfs_dir_operations; |
76 | extern const struct file_operations configfs_file_operations; | 76 | extern const struct file_operations configfs_file_operations; |
77 | extern const struct file_operations bin_fops; | 77 | extern const struct file_operations bin_fops; |
78 | extern struct inode_operations configfs_dir_inode_operations; | 78 | extern const struct inode_operations configfs_dir_inode_operations; |
79 | extern struct inode_operations configfs_symlink_inode_operations; | 79 | extern const struct inode_operations configfs_symlink_inode_operations; |
80 | 80 | ||
81 | extern int configfs_symlink(struct inode *dir, struct dentry *dentry, | 81 | extern int configfs_symlink(struct inode *dir, struct dentry *dentry, |
82 | const char *symname); | 82 | const char *symname); |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 1814ba446809..34750d5e4ff2 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -72,11 +72,10 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare | |||
72 | { | 72 | { |
73 | struct configfs_dirent * sd; | 73 | struct configfs_dirent * sd; |
74 | 74 | ||
75 | sd = kmem_cache_alloc(configfs_dir_cachep, GFP_KERNEL); | 75 | sd = kmem_cache_zalloc(configfs_dir_cachep, GFP_KERNEL); |
76 | if (!sd) | 76 | if (!sd) |
77 | return NULL; | 77 | return NULL; |
78 | 78 | ||
79 | memset(sd, 0, sizeof(*sd)); | ||
80 | atomic_set(&sd->s_count, 1); | 79 | atomic_set(&sd->s_count, 1); |
81 | INIT_LIST_HEAD(&sd->s_links); | 80 | INIT_LIST_HEAD(&sd->s_links); |
82 | INIT_LIST_HEAD(&sd->s_children); | 81 | INIT_LIST_HEAD(&sd->s_children); |
@@ -931,7 +930,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
931 | return 0; | 930 | return 0; |
932 | } | 931 | } |
933 | 932 | ||
934 | struct inode_operations configfs_dir_inode_operations = { | 933 | const struct inode_operations configfs_dir_inode_operations = { |
935 | .mkdir = configfs_mkdir, | 934 | .mkdir = configfs_mkdir, |
936 | .rmdir = configfs_rmdir, | 935 | .rmdir = configfs_rmdir, |
937 | .symlink = configfs_symlink, | 936 | .symlink = configfs_symlink, |
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index fb18917954a9..2ec9beac17cf 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c | |||
@@ -49,7 +49,7 @@ static struct backing_dev_info configfs_backing_dev_info = { | |||
49 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, | 49 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static struct inode_operations configfs_inode_operations ={ | 52 | static const struct inode_operations configfs_inode_operations ={ |
53 | .setattr = configfs_setattr, | 53 | .setattr = configfs_setattr, |
54 | }; | 54 | }; |
55 | 55 | ||
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index ed678529ebb2..6f573004cd7d 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c | |||
@@ -41,7 +41,7 @@ struct super_block * configfs_sb = NULL; | |||
41 | struct kmem_cache *configfs_dir_cachep; | 41 | struct kmem_cache *configfs_dir_cachep; |
42 | static int configfs_mnt_count = 0; | 42 | static int configfs_mnt_count = 0; |
43 | 43 | ||
44 | static struct super_operations configfs_ops = { | 44 | static const struct super_operations configfs_ops = { |
45 | .statfs = simple_statfs, | 45 | .statfs = simple_statfs, |
46 | .drop_inode = generic_delete_inode, | 46 | .drop_inode = generic_delete_inode, |
47 | }; | 47 | }; |
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index fb65e0800a86..22700d2857da 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c | |||
@@ -272,7 +272,7 @@ static void configfs_put_link(struct dentry *dentry, struct nameidata *nd, | |||
272 | } | 272 | } |
273 | } | 273 | } |
274 | 274 | ||
275 | struct inode_operations configfs_symlink_inode_operations = { | 275 | const struct inode_operations configfs_symlink_inode_operations = { |
276 | .follow_link = configfs_follow_link, | 276 | .follow_link = configfs_follow_link, |
277 | .readlink = generic_readlink, | 277 | .readlink = generic_readlink, |
278 | .put_link = configfs_put_link, | 278 | .put_link = configfs_put_link, |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 6db03fb089dc..facd0c89be8f 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -27,8 +27,8 @@ | |||
27 | 27 | ||
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | 29 | ||
30 | static struct super_operations cramfs_ops; | 30 | static const struct super_operations cramfs_ops; |
31 | static struct inode_operations cramfs_dir_inode_operations; | 31 | static const struct inode_operations cramfs_dir_inode_operations; |
32 | static const struct file_operations cramfs_directory_operations; | 32 | static const struct file_operations cramfs_directory_operations; |
33 | static const struct address_space_operations cramfs_aops; | 33 | static const struct address_space_operations cramfs_aops; |
34 | 34 | ||
@@ -518,11 +518,11 @@ static const struct file_operations cramfs_directory_operations = { | |||
518 | .readdir = cramfs_readdir, | 518 | .readdir = cramfs_readdir, |
519 | }; | 519 | }; |
520 | 520 | ||
521 | static struct inode_operations cramfs_dir_inode_operations = { | 521 | static const struct inode_operations cramfs_dir_inode_operations = { |
522 | .lookup = cramfs_lookup, | 522 | .lookup = cramfs_lookup, |
523 | }; | 523 | }; |
524 | 524 | ||
525 | static struct super_operations cramfs_ops = { | 525 | static const struct super_operations cramfs_ops = { |
526 | .put_super = cramfs_put_super, | 526 | .put_super = cramfs_put_super, |
527 | .remount_fs = cramfs_remount, | 527 | .remount_fs = cramfs_remount, |
528 | .statfs = cramfs_statfs, | 528 | .statfs = cramfs_statfs, |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index bf3901ab1744..682f928b7f4d 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
19 | #include <linux/namei.h> | ||
19 | #include <linux/debugfs.h> | 20 | #include <linux/debugfs.h> |
20 | 21 | ||
21 | static ssize_t default_read_file(struct file *file, char __user *buf, | 22 | static ssize_t default_read_file(struct file *file, char __user *buf, |
@@ -44,6 +45,17 @@ const struct file_operations debugfs_file_operations = { | |||
44 | .open = default_open, | 45 | .open = default_open, |
45 | }; | 46 | }; |
46 | 47 | ||
48 | static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
49 | { | ||
50 | nd_set_link(nd, dentry->d_inode->i_private); | ||
51 | return NULL; | ||
52 | } | ||
53 | |||
54 | const struct inode_operations debugfs_link_operations = { | ||
55 | .readlink = generic_readlink, | ||
56 | .follow_link = debugfs_follow_link, | ||
57 | }; | ||
58 | |||
47 | static void debugfs_u8_set(void *data, u64 val) | 59 | static void debugfs_u8_set(void *data, u64 val) |
48 | { | 60 | { |
49 | *(u8 *)data = val; | 61 | *(u8 *)data = val; |
@@ -254,7 +266,7 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf, | |||
254 | blob->size); | 266 | blob->size); |
255 | } | 267 | } |
256 | 268 | ||
257 | static struct file_operations fops_blob = { | 269 | static const struct file_operations fops_blob = { |
258 | .read = read_file_blob, | 270 | .read = read_file_blob, |
259 | .open = default_open, | 271 | .open = default_open, |
260 | }; | 272 | }; |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index c692487346ea..7b324cfebcb1 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -25,11 +25,13 @@ | |||
25 | #include <linux/namei.h> | 25 | #include <linux/namei.h> |
26 | #include <linux/debugfs.h> | 26 | #include <linux/debugfs.h> |
27 | #include <linux/fsnotify.h> | 27 | #include <linux/fsnotify.h> |
28 | #include <linux/string.h> | ||
28 | 29 | ||
29 | #define DEBUGFS_MAGIC 0x64626720 | 30 | #define DEBUGFS_MAGIC 0x64626720 |
30 | 31 | ||
31 | /* declared over in file.c */ | 32 | /* declared over in file.c */ |
32 | extern struct file_operations debugfs_file_operations; | 33 | extern struct file_operations debugfs_file_operations; |
34 | extern struct inode_operations debugfs_link_operations; | ||
33 | 35 | ||
34 | static struct vfsmount *debugfs_mount; | 36 | static struct vfsmount *debugfs_mount; |
35 | static int debugfs_mount_count; | 37 | static int debugfs_mount_count; |
@@ -51,6 +53,9 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d | |||
51 | case S_IFREG: | 53 | case S_IFREG: |
52 | inode->i_fop = &debugfs_file_operations; | 54 | inode->i_fop = &debugfs_file_operations; |
53 | break; | 55 | break; |
56 | case S_IFLNK: | ||
57 | inode->i_op = &debugfs_link_operations; | ||
58 | break; | ||
54 | case S_IFDIR: | 59 | case S_IFDIR: |
55 | inode->i_op = &simple_dir_inode_operations; | 60 | inode->i_op = &simple_dir_inode_operations; |
56 | inode->i_fop = &simple_dir_operations; | 61 | inode->i_fop = &simple_dir_operations; |
@@ -96,6 +101,12 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
96 | return res; | 101 | return res; |
97 | } | 102 | } |
98 | 103 | ||
104 | static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode) | ||
105 | { | ||
106 | mode = (mode & S_IALLUGO) | S_IFLNK; | ||
107 | return debugfs_mknod(dir, dentry, mode, 0); | ||
108 | } | ||
109 | |||
99 | static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) | 110 | static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) |
100 | { | 111 | { |
101 | int res; | 112 | int res; |
@@ -158,10 +169,17 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
158 | mutex_lock(&parent->d_inode->i_mutex); | 169 | mutex_lock(&parent->d_inode->i_mutex); |
159 | *dentry = lookup_one_len(name, parent, strlen(name)); | 170 | *dentry = lookup_one_len(name, parent, strlen(name)); |
160 | if (!IS_ERR(*dentry)) { | 171 | if (!IS_ERR(*dentry)) { |
161 | if ((mode & S_IFMT) == S_IFDIR) | 172 | switch (mode & S_IFMT) { |
173 | case S_IFDIR: | ||
162 | error = debugfs_mkdir(parent->d_inode, *dentry, mode); | 174 | error = debugfs_mkdir(parent->d_inode, *dentry, mode); |
163 | else | 175 | break; |
176 | case S_IFLNK: | ||
177 | error = debugfs_link(parent->d_inode, *dentry, mode); | ||
178 | break; | ||
179 | default: | ||
164 | error = debugfs_create(parent->d_inode, *dentry, mode); | 180 | error = debugfs_create(parent->d_inode, *dentry, mode); |
181 | break; | ||
182 | } | ||
165 | dput(*dentry); | 183 | dput(*dentry); |
166 | } else | 184 | } else |
167 | error = PTR_ERR(*dentry); | 185 | error = PTR_ERR(*dentry); |
@@ -194,9 +212,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
194 | * you are responsible here.) If an error occurs, %NULL will be returned. | 212 | * you are responsible here.) If an error occurs, %NULL will be returned. |
195 | * | 213 | * |
196 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be | 214 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
197 | * returned. It is not wise to check for this value, but rather, check for | 215 | * returned. |
198 | * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling | ||
199 | * code. | ||
200 | */ | 216 | */ |
201 | struct dentry *debugfs_create_file(const char *name, mode_t mode, | 217 | struct dentry *debugfs_create_file(const char *name, mode_t mode, |
202 | struct dentry *parent, void *data, | 218 | struct dentry *parent, void *data, |
@@ -246,9 +262,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file); | |||
246 | * you are responsible here.) If an error occurs, %NULL will be returned. | 262 | * you are responsible here.) If an error occurs, %NULL will be returned. |
247 | * | 263 | * |
248 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be | 264 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be |
249 | * returned. It is not wise to check for this value, but rather, check for | 265 | * returned. |
250 | * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling | ||
251 | * code. | ||
252 | */ | 266 | */ |
253 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) | 267 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) |
254 | { | 268 | { |
@@ -259,6 +273,47 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) | |||
259 | EXPORT_SYMBOL_GPL(debugfs_create_dir); | 273 | EXPORT_SYMBOL_GPL(debugfs_create_dir); |
260 | 274 | ||
261 | /** | 275 | /** |
276 | * debugfs_create_symlink- create a symbolic link in the debugfs filesystem | ||
277 | * @name: a pointer to a string containing the name of the symbolic link to | ||
278 | * create. | ||
279 | * @parent: a pointer to the parent dentry for this symbolic link. This | ||
280 | * should be a directory dentry if set. If this paramater is NULL, | ||
281 | * then the symbolic link will be created in the root of the debugfs | ||
282 | * filesystem. | ||
283 | * @target: a pointer to a string containing the path to the target of the | ||
284 | * symbolic link. | ||
285 | * | ||
286 | * This function creates a symbolic link with the given name in debugfs that | ||
287 | * links to the given target path. | ||
288 | * | ||
289 | * This function will return a pointer to a dentry if it succeeds. This | ||
290 | * pointer must be passed to the debugfs_remove() function when the symbolic | ||
291 | * link is to be removed (no automatic cleanup happens if your module is | ||
292 | * unloaded, you are responsible here.) If an error occurs, %NULL will be | ||
293 | * returned. | ||
294 | * | ||
295 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be | ||
296 | * returned. | ||
297 | */ | ||
298 | struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, | ||
299 | const char *target) | ||
300 | { | ||
301 | struct dentry *result; | ||
302 | char *link; | ||
303 | |||
304 | link = kstrdup(target, GFP_KERNEL); | ||
305 | if (!link) | ||
306 | return NULL; | ||
307 | |||
308 | result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link, | ||
309 | NULL); | ||
310 | if (!result) | ||
311 | kfree(link); | ||
312 | return result; | ||
313 | } | ||
314 | EXPORT_SYMBOL_GPL(debugfs_create_symlink); | ||
315 | |||
316 | /** | ||
262 | * debugfs_remove - removes a file or directory from the debugfs filesystem | 317 | * debugfs_remove - removes a file or directory from the debugfs filesystem |
263 | * @dentry: a pointer to a the dentry of the file or directory to be | 318 | * @dentry: a pointer to a the dentry of the file or directory to be |
264 | * removed. | 319 | * removed. |
@@ -287,15 +342,22 @@ void debugfs_remove(struct dentry *dentry) | |||
287 | if (debugfs_positive(dentry)) { | 342 | if (debugfs_positive(dentry)) { |
288 | if (dentry->d_inode) { | 343 | if (dentry->d_inode) { |
289 | dget(dentry); | 344 | dget(dentry); |
290 | if (S_ISDIR(dentry->d_inode->i_mode)) { | 345 | switch (dentry->d_inode->i_mode & S_IFMT) { |
346 | case S_IFDIR: | ||
291 | ret = simple_rmdir(parent->d_inode, dentry); | 347 | ret = simple_rmdir(parent->d_inode, dentry); |
292 | if (ret) | 348 | if (ret) |
293 | printk(KERN_ERR | 349 | printk(KERN_ERR |
294 | "DebugFS rmdir on %s failed : " | 350 | "DebugFS rmdir on %s failed : " |
295 | "directory not empty.\n", | 351 | "directory not empty.\n", |
296 | dentry->d_name.name); | 352 | dentry->d_name.name); |
297 | } else | 353 | break; |
354 | case S_IFLNK: | ||
355 | kfree(dentry->d_inode->i_private); | ||
356 | /* fall through */ | ||
357 | default: | ||
298 | simple_unlink(parent->d_inode, dentry); | 358 | simple_unlink(parent->d_inode, dentry); |
359 | break; | ||
360 | } | ||
299 | if (!ret) | 361 | if (!ret) |
300 | d_delete(dentry); | 362 | d_delete(dentry); |
301 | dput(dentry); | 363 | dput(dentry); |
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 5f7b5a6025bf..643e57b622bd 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -91,7 +91,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data) | |||
91 | return 0; | 91 | return 0; |
92 | } | 92 | } |
93 | 93 | ||
94 | static struct super_operations devpts_sops = { | 94 | static const struct super_operations devpts_sops = { |
95 | .statfs = simple_statfs, | 95 | .statfs = simple_statfs, |
96 | .remount_fs = devpts_remount, | 96 | .remount_fs = devpts_remount, |
97 | }; | 97 | }; |
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index ca94a837a5bb..61ba670b9e02 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c | |||
@@ -287,7 +287,7 @@ static int rsb_open(struct inode *inode, struct file *file) | |||
287 | return 0; | 287 | return 0; |
288 | } | 288 | } |
289 | 289 | ||
290 | static struct file_operations rsb_fops = { | 290 | static const struct file_operations rsb_fops = { |
291 | .owner = THIS_MODULE, | 291 | .owner = THIS_MODULE, |
292 | .open = rsb_open, | 292 | .open = rsb_open, |
293 | .read = seq_read, | 293 | .read = seq_read, |
@@ -331,7 +331,7 @@ static ssize_t waiters_read(struct file *file, char __user *userbuf, | |||
331 | return rv; | 331 | return rv; |
332 | } | 332 | } |
333 | 333 | ||
334 | static struct file_operations waiters_fops = { | 334 | static const struct file_operations waiters_fops = { |
335 | .owner = THIS_MODULE, | 335 | .owner = THIS_MODULE, |
336 | .open = waiters_open, | 336 | .open = waiters_open, |
337 | .read = waiters_read | 337 | .read = waiters_read |
diff --git a/fs/dlm/lowcomms-tcp.c b/fs/dlm/lowcomms-tcp.c index f1efd17b2614..07e0a122c32f 100644 --- a/fs/dlm/lowcomms-tcp.c +++ b/fs/dlm/lowcomms-tcp.c | |||
@@ -268,12 +268,12 @@ static void close_connection(struct connection *con, bool and_other) | |||
268 | static int receive_from_sock(struct connection *con) | 268 | static int receive_from_sock(struct connection *con) |
269 | { | 269 | { |
270 | int ret = 0; | 270 | int ret = 0; |
271 | struct msghdr msg; | 271 | struct msghdr msg = {}; |
272 | struct iovec iov[2]; | 272 | struct kvec iov[2]; |
273 | mm_segment_t fs; | ||
274 | unsigned len; | 273 | unsigned len; |
275 | int r; | 274 | int r; |
276 | int call_again_soon = 0; | 275 | int call_again_soon = 0; |
276 | int nvec; | ||
277 | 277 | ||
278 | mutex_lock(&con->sock_mutex); | 278 | mutex_lock(&con->sock_mutex); |
279 | 279 | ||
@@ -293,21 +293,13 @@ static int receive_from_sock(struct connection *con) | |||
293 | cbuf_init(&con->cb, PAGE_CACHE_SIZE); | 293 | cbuf_init(&con->cb, PAGE_CACHE_SIZE); |
294 | } | 294 | } |
295 | 295 | ||
296 | msg.msg_control = NULL; | ||
297 | msg.msg_controllen = 0; | ||
298 | msg.msg_iovlen = 1; | ||
299 | msg.msg_iov = iov; | ||
300 | msg.msg_name = NULL; | ||
301 | msg.msg_namelen = 0; | ||
302 | msg.msg_flags = 0; | ||
303 | |||
304 | /* | 296 | /* |
305 | * iov[0] is the bit of the circular buffer between the current end | 297 | * iov[0] is the bit of the circular buffer between the current end |
306 | * point (cb.base + cb.len) and the end of the buffer. | 298 | * point (cb.base + cb.len) and the end of the buffer. |
307 | */ | 299 | */ |
308 | iov[0].iov_len = con->cb.base - cbuf_data(&con->cb); | 300 | iov[0].iov_len = con->cb.base - cbuf_data(&con->cb); |
309 | iov[0].iov_base = page_address(con->rx_page) + cbuf_data(&con->cb); | 301 | iov[0].iov_base = page_address(con->rx_page) + cbuf_data(&con->cb); |
310 | iov[1].iov_len = 0; | 302 | nvec = 1; |
311 | 303 | ||
312 | /* | 304 | /* |
313 | * iov[1] is the bit of the circular buffer between the start of the | 305 | * iov[1] is the bit of the circular buffer between the start of the |
@@ -317,15 +309,12 @@ static int receive_from_sock(struct connection *con) | |||
317 | iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb); | 309 | iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb); |
318 | iov[1].iov_len = con->cb.base; | 310 | iov[1].iov_len = con->cb.base; |
319 | iov[1].iov_base = page_address(con->rx_page); | 311 | iov[1].iov_base = page_address(con->rx_page); |
320 | msg.msg_iovlen = 2; | 312 | nvec = 2; |
321 | } | 313 | } |
322 | len = iov[0].iov_len + iov[1].iov_len; | 314 | len = iov[0].iov_len + iov[1].iov_len; |
323 | 315 | ||
324 | fs = get_fs(); | 316 | r = ret = kernel_recvmsg(con->sock, &msg, iov, nvec, len, |
325 | set_fs(get_ds()); | ||
326 | r = ret = sock_recvmsg(con->sock, &msg, len, | ||
327 | MSG_DONTWAIT | MSG_NOSIGNAL); | 317 | MSG_DONTWAIT | MSG_NOSIGNAL); |
328 | set_fs(fs); | ||
329 | 318 | ||
330 | if (ret <= 0) | 319 | if (ret <= 0) |
331 | goto out_close; | 320 | goto out_close; |
diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c index 5352b03ff5aa..f858fef6e41c 100644 --- a/fs/dlm/memory.c +++ b/fs/dlm/memory.c | |||
@@ -76,9 +76,7 @@ struct dlm_lkb *allocate_lkb(struct dlm_ls *ls) | |||
76 | { | 76 | { |
77 | struct dlm_lkb *lkb; | 77 | struct dlm_lkb *lkb; |
78 | 78 | ||
79 | lkb = kmem_cache_alloc(lkb_cache, GFP_KERNEL); | 79 | lkb = kmem_cache_zalloc(lkb_cache, GFP_KERNEL); |
80 | if (lkb) | ||
81 | memset(lkb, 0, sizeof(*lkb)); | ||
82 | return lkb; | 80 | return lkb; |
83 | } | 81 | } |
84 | 82 | ||
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index d378b7fe2a1e..40db61dc95f2 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | static const char *name_prefix="dlm"; | 26 | static const char *name_prefix="dlm"; |
27 | static struct miscdevice ctl_device; | 27 | static struct miscdevice ctl_device; |
28 | static struct file_operations device_fops; | 28 | static const struct file_operations device_fops; |
29 | 29 | ||
30 | #ifdef CONFIG_COMPAT | 30 | #ifdef CONFIG_COMPAT |
31 | 31 | ||
@@ -759,7 +759,7 @@ static int ctl_device_close(struct inode *inode, struct file *file) | |||
759 | return 0; | 759 | return 0; |
760 | } | 760 | } |
761 | 761 | ||
762 | static struct file_operations device_fops = { | 762 | static const struct file_operations device_fops = { |
763 | .open = device_open, | 763 | .open = device_open, |
764 | .release = device_close, | 764 | .release = device_close, |
765 | .read = device_read, | 765 | .read = device_read, |
@@ -768,7 +768,7 @@ static struct file_operations device_fops = { | |||
768 | .owner = THIS_MODULE, | 768 | .owner = THIS_MODULE, |
769 | }; | 769 | }; |
770 | 770 | ||
771 | static struct file_operations ctl_device_fops = { | 771 | static const struct file_operations ctl_device_fops = { |
772 | .open = ctl_device_open, | 772 | .open = ctl_device_open, |
773 | .release = ctl_device_close, | 773 | .release = ctl_device_close, |
774 | .write = device_write, | 774 | .write = device_write, |
diff --git a/fs/dquot.c b/fs/dquot.c index 0952cc474d9a..b16f991662c1 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -79,6 +79,7 @@ | |||
79 | #include <linux/buffer_head.h> | 79 | #include <linux/buffer_head.h> |
80 | #include <linux/capability.h> | 80 | #include <linux/capability.h> |
81 | #include <linux/quotaops.h> | 81 | #include <linux/quotaops.h> |
82 | #include <linux/writeback.h> /* for inode_lock, oddly enough.. */ | ||
82 | 83 | ||
83 | #include <asm/uaccess.h> | 84 | #include <asm/uaccess.h> |
84 | 85 | ||
@@ -600,11 +601,10 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) | |||
600 | { | 601 | { |
601 | struct dquot *dquot; | 602 | struct dquot *dquot; |
602 | 603 | ||
603 | dquot = kmem_cache_alloc(dquot_cachep, GFP_NOFS); | 604 | dquot = kmem_cache_zalloc(dquot_cachep, GFP_NOFS); |
604 | if(!dquot) | 605 | if(!dquot) |
605 | return NODQUOT; | 606 | return NODQUOT; |
606 | 607 | ||
607 | memset((caddr_t)dquot, 0, sizeof(struct dquot)); | ||
608 | mutex_init(&dquot->dq_lock); | 608 | mutex_init(&dquot->dq_lock); |
609 | INIT_LIST_HEAD(&dquot->dq_free); | 609 | INIT_LIST_HEAD(&dquot->dq_free); |
610 | INIT_LIST_HEAD(&dquot->dq_inuse); | 610 | INIT_LIST_HEAD(&dquot->dq_inuse); |
@@ -688,23 +688,27 @@ static int dqinit_needed(struct inode *inode, int type) | |||
688 | /* This routine is guarded by dqonoff_mutex mutex */ | 688 | /* This routine is guarded by dqonoff_mutex mutex */ |
689 | static void add_dquot_ref(struct super_block *sb, int type) | 689 | static void add_dquot_ref(struct super_block *sb, int type) |
690 | { | 690 | { |
691 | struct list_head *p; | 691 | struct inode *inode; |
692 | 692 | ||
693 | restart: | 693 | restart: |
694 | file_list_lock(); | 694 | spin_lock(&inode_lock); |
695 | list_for_each(p, &sb->s_files) { | 695 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { |
696 | struct file *filp = list_entry(p, struct file, f_u.fu_list); | 696 | if (!atomic_read(&inode->i_writecount)) |
697 | struct inode *inode = filp->f_path.dentry->d_inode; | 697 | continue; |
698 | if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { | 698 | if (!dqinit_needed(inode, type)) |
699 | struct dentry *dentry = dget(filp->f_path.dentry); | 699 | continue; |
700 | file_list_unlock(); | 700 | if (inode->i_state & (I_FREEING|I_WILL_FREE)) |
701 | sb->dq_op->initialize(inode, type); | 701 | continue; |
702 | dput(dentry); | 702 | |
703 | /* As we may have blocked we had better restart... */ | 703 | __iget(inode); |
704 | goto restart; | 704 | spin_unlock(&inode_lock); |
705 | } | 705 | |
706 | sb->dq_op->initialize(inode, type); | ||
707 | iput(inode); | ||
708 | /* As we may have blocked we had better restart... */ | ||
709 | goto restart; | ||
706 | } | 710 | } |
707 | file_list_unlock(); | 711 | spin_unlock(&inode_lock); |
708 | } | 712 | } |
709 | 713 | ||
710 | /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ | 714 | /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ |
@@ -756,15 +760,30 @@ static void put_dquot_list(struct list_head *tofree_head) | |||
756 | } | 760 | } |
757 | } | 761 | } |
758 | 762 | ||
763 | static void remove_dquot_ref(struct super_block *sb, int type, | ||
764 | struct list_head *tofree_head) | ||
765 | { | ||
766 | struct inode *inode; | ||
767 | |||
768 | spin_lock(&inode_lock); | ||
769 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { | ||
770 | if (!IS_NOQUOTA(inode)) | ||
771 | remove_inode_dquot_ref(inode, type, tofree_head); | ||
772 | } | ||
773 | spin_unlock(&inode_lock); | ||
774 | } | ||
775 | |||
759 | /* Gather all references from inodes and drop them */ | 776 | /* Gather all references from inodes and drop them */ |
760 | static void drop_dquot_ref(struct super_block *sb, int type) | 777 | static void drop_dquot_ref(struct super_block *sb, int type) |
761 | { | 778 | { |
762 | LIST_HEAD(tofree_head); | 779 | LIST_HEAD(tofree_head); |
763 | 780 | ||
764 | down_write(&sb_dqopt(sb)->dqptr_sem); | 781 | if (sb->dq_op) { |
765 | remove_dquot_ref(sb, type, &tofree_head); | 782 | down_write(&sb_dqopt(sb)->dqptr_sem); |
766 | up_write(&sb_dqopt(sb)->dqptr_sem); | 783 | remove_dquot_ref(sb, type, &tofree_head); |
767 | put_dquot_list(&tofree_head); | 784 | up_write(&sb_dqopt(sb)->dqptr_sem); |
785 | put_dquot_list(&tofree_head); | ||
786 | } | ||
768 | } | 787 | } |
769 | 788 | ||
770 | static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number) | 789 | static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number) |
@@ -1822,7 +1841,7 @@ static int __init dquot_init(void) | |||
1822 | 1841 | ||
1823 | printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__); | 1842 | printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__); |
1824 | 1843 | ||
1825 | register_sysctl_table(sys_table, 0); | 1844 | register_sysctl_table(sys_table); |
1826 | 1845 | ||
1827 | dquot_cachep = kmem_cache_create("dquot", | 1846 | dquot_cachep = kmem_cache_create("dquot", |
1828 | sizeof(struct dquot), sizeof(unsigned long) * 4, | 1847 | sizeof(struct dquot), sizeof(unsigned long) * 4, |
diff --git a/fs/drop_caches.c b/fs/drop_caches.c index 4e4762389bdc..03ea7696fe39 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c | |||
@@ -20,7 +20,7 @@ static void drop_pagecache_sb(struct super_block *sb) | |||
20 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { | 20 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { |
21 | if (inode->i_state & (I_FREEING|I_WILL_FREE)) | 21 | if (inode->i_state & (I_FREEING|I_WILL_FREE)) |
22 | continue; | 22 | continue; |
23 | invalidate_inode_pages(inode->i_mapping); | 23 | invalidate_mapping_pages(inode->i_mapping, 0, -1); |
24 | } | 24 | } |
25 | spin_unlock(&inode_lock); | 25 | spin_unlock(&inode_lock); |
26 | } | 26 | } |
diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile index ca6562451eeb..1f1107237eab 100644 --- a/fs/ecryptfs/Makefile +++ b/fs/ecryptfs/Makefile | |||
@@ -4,4 +4,4 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o | 5 | obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o |
6 | 6 | ||
7 | ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o debug.o | 7 | ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o messaging.o netlink.o debug.o |
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 7196f50fe152..6ac630625b70 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-2004 Erez Zadok | 4 | * Copyright (C) 1997-2004 Erez Zadok |
5 | * Copyright (C) 2001-2004 Stony Brook University | 5 | * Copyright (C) 2001-2004 Stony Brook University |
6 | * Copyright (C) 2004-2006 International Business Machines Corp. | 6 | * Copyright (C) 2004-2007 International Business Machines Corp. |
7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
8 | * Michael C. Thompson <mcthomps@us.ibm.com> | 8 | * Michael C. Thompson <mcthomps@us.ibm.com> |
9 | * | 9 | * |
@@ -207,7 +207,7 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) | |||
207 | mutex_init(&crypt_stat->cs_mutex); | 207 | mutex_init(&crypt_stat->cs_mutex); |
208 | mutex_init(&crypt_stat->cs_tfm_mutex); | 208 | mutex_init(&crypt_stat->cs_tfm_mutex); |
209 | mutex_init(&crypt_stat->cs_hash_tfm_mutex); | 209 | mutex_init(&crypt_stat->cs_hash_tfm_mutex); |
210 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED); | 210 | crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED; |
211 | } | 211 | } |
212 | 212 | ||
213 | /** | 213 | /** |
@@ -305,8 +305,7 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, | |||
305 | int rc = 0; | 305 | int rc = 0; |
306 | 306 | ||
307 | BUG_ON(!crypt_stat || !crypt_stat->tfm | 307 | BUG_ON(!crypt_stat || !crypt_stat->tfm |
308 | || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, | 308 | || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)); |
309 | ECRYPTFS_STRUCT_INITIALIZED)); | ||
310 | if (unlikely(ecryptfs_verbosity > 0)) { | 309 | if (unlikely(ecryptfs_verbosity > 0)) { |
311 | ecryptfs_printk(KERN_DEBUG, "Key size [%d]; key:\n", | 310 | ecryptfs_printk(KERN_DEBUG, "Key size [%d]; key:\n", |
312 | crypt_stat->key_size); | 311 | crypt_stat->key_size); |
@@ -429,10 +428,10 @@ static int ecryptfs_read_in_page(struct ecryptfs_page_crypt_context *ctx, | |||
429 | goto out; | 428 | goto out; |
430 | } | 429 | } |
431 | } else { | 430 | } else { |
432 | rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL, | 431 | *lower_page = grab_cache_page(lower_inode->i_mapping, |
433 | lower_inode, | 432 | lower_page_idx); |
434 | lower_page_idx); | 433 | if (!(*lower_page)) { |
435 | if (rc) { | 434 | rc = -EINVAL; |
436 | ecryptfs_printk( | 435 | ecryptfs_printk( |
437 | KERN_ERR, "Error attempting to grab and map " | 436 | KERN_ERR, "Error attempting to grab and map " |
438 | "lower page with index [0x%.16x]; rc = [%d]\n", | 437 | "lower page with index [0x%.16x]; rc = [%d]\n", |
@@ -485,7 +484,7 @@ int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx) | |||
485 | lower_inode = ecryptfs_inode_to_lower(ctx->page->mapping->host); | 484 | lower_inode = ecryptfs_inode_to_lower(ctx->page->mapping->host); |
486 | inode_info = ecryptfs_inode_to_private(ctx->page->mapping->host); | 485 | inode_info = ecryptfs_inode_to_private(ctx->page->mapping->host); |
487 | crypt_stat = &inode_info->crypt_stat; | 486 | crypt_stat = &inode_info->crypt_stat; |
488 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) { | 487 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { |
489 | rc = ecryptfs_copy_page_to_lower(ctx->page, lower_inode, | 488 | rc = ecryptfs_copy_page_to_lower(ctx->page, lower_inode, |
490 | ctx->param.lower_file); | 489 | ctx->param.lower_file); |
491 | if (rc) | 490 | if (rc) |
@@ -617,7 +616,7 @@ int ecryptfs_decrypt_page(struct file *file, struct page *page) | |||
617 | crypt_stat = &(ecryptfs_inode_to_private( | 616 | crypt_stat = &(ecryptfs_inode_to_private( |
618 | page->mapping->host)->crypt_stat); | 617 | page->mapping->host)->crypt_stat); |
619 | lower_inode = ecryptfs_inode_to_lower(page->mapping->host); | 618 | lower_inode = ecryptfs_inode_to_lower(page->mapping->host); |
620 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) { | 619 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { |
621 | rc = ecryptfs_do_readpage(file, page, page->index); | 620 | rc = ecryptfs_do_readpage(file, page, page->index); |
622 | if (rc) | 621 | if (rc) |
623 | ecryptfs_printk(KERN_ERR, "Error attempting to copy " | 622 | ecryptfs_printk(KERN_ERR, "Error attempting to copy " |
@@ -828,9 +827,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) | |||
828 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 827 | mutex_unlock(&crypt_stat->cs_tfm_mutex); |
829 | goto out; | 828 | goto out; |
830 | } | 829 | } |
831 | crypto_blkcipher_set_flags(crypt_stat->tfm, | 830 | crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY); |
832 | (ECRYPTFS_DEFAULT_CHAINING_MODE | ||
833 | | CRYPTO_TFM_REQ_WEAK_KEY)); | ||
834 | mutex_unlock(&crypt_stat->cs_tfm_mutex); | 831 | mutex_unlock(&crypt_stat->cs_tfm_mutex); |
835 | rc = 0; | 832 | rc = 0; |
836 | out: | 833 | out: |
@@ -865,7 +862,10 @@ void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat) | |||
865 | ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; | 862 | ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; |
866 | } else | 863 | } else |
867 | crypt_stat->header_extent_size = PAGE_CACHE_SIZE; | 864 | crypt_stat->header_extent_size = PAGE_CACHE_SIZE; |
868 | crypt_stat->num_header_extents_at_front = 1; | 865 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) |
866 | crypt_stat->num_header_extents_at_front = 0; | ||
867 | else | ||
868 | crypt_stat->num_header_extents_at_front = 1; | ||
869 | } | 869 | } |
870 | 870 | ||
871 | /** | 871 | /** |
@@ -881,7 +881,7 @@ int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat) | |||
881 | 881 | ||
882 | BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE); | 882 | BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE); |
883 | BUG_ON(crypt_stat->iv_bytes <= 0); | 883 | BUG_ON(crypt_stat->iv_bytes <= 0); |
884 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID)) { | 884 | if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { |
885 | rc = -EINVAL; | 885 | rc = -EINVAL; |
886 | ecryptfs_printk(KERN_WARNING, "Session key not valid; " | 886 | ecryptfs_printk(KERN_WARNING, "Session key not valid; " |
887 | "cannot generate root IV\n"); | 887 | "cannot generate root IV\n"); |
@@ -898,8 +898,7 @@ int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat) | |||
898 | out: | 898 | out: |
899 | if (rc) { | 899 | if (rc) { |
900 | memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes); | 900 | memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes); |
901 | ECRYPTFS_SET_FLAG(crypt_stat->flags, | 901 | crypt_stat->flags |= ECRYPTFS_SECURITY_WARNING; |
902 | ECRYPTFS_SECURITY_WARNING); | ||
903 | } | 902 | } |
904 | return rc; | 903 | return rc; |
905 | } | 904 | } |
@@ -907,7 +906,7 @@ out: | |||
907 | static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat) | 906 | static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat) |
908 | { | 907 | { |
909 | get_random_bytes(crypt_stat->key, crypt_stat->key_size); | 908 | get_random_bytes(crypt_stat->key, crypt_stat->key_size); |
910 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID); | 909 | crypt_stat->flags |= ECRYPTFS_KEY_VALID; |
911 | ecryptfs_compute_root_iv(crypt_stat); | 910 | ecryptfs_compute_root_iv(crypt_stat); |
912 | if (unlikely(ecryptfs_verbosity > 0)) { | 911 | if (unlikely(ecryptfs_verbosity > 0)) { |
913 | ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n"); | 912 | ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n"); |
@@ -917,6 +916,22 @@ static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat) | |||
917 | } | 916 | } |
918 | 917 | ||
919 | /** | 918 | /** |
919 | * ecryptfs_copy_mount_wide_flags_to_inode_flags | ||
920 | * | ||
921 | * This function propagates the mount-wide flags to individual inode | ||
922 | * flags. | ||
923 | */ | ||
924 | static void ecryptfs_copy_mount_wide_flags_to_inode_flags( | ||
925 | struct ecryptfs_crypt_stat *crypt_stat, | ||
926 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat) | ||
927 | { | ||
928 | if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) | ||
929 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; | ||
930 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) | ||
931 | crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED; | ||
932 | } | ||
933 | |||
934 | /** | ||
920 | * ecryptfs_set_default_crypt_stat_vals | 935 | * ecryptfs_set_default_crypt_stat_vals |
921 | * @crypt_stat | 936 | * @crypt_stat |
922 | * | 937 | * |
@@ -926,10 +941,12 @@ static void ecryptfs_set_default_crypt_stat_vals( | |||
926 | struct ecryptfs_crypt_stat *crypt_stat, | 941 | struct ecryptfs_crypt_stat *crypt_stat, |
927 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat) | 942 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat) |
928 | { | 943 | { |
944 | ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, | ||
945 | mount_crypt_stat); | ||
929 | ecryptfs_set_default_sizes(crypt_stat); | 946 | ecryptfs_set_default_sizes(crypt_stat); |
930 | strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER); | 947 | strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER); |
931 | crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES; | 948 | crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES; |
932 | ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID); | 949 | crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID); |
933 | crypt_stat->file_version = ECRYPTFS_FILE_VERSION; | 950 | crypt_stat->file_version = ECRYPTFS_FILE_VERSION; |
934 | crypt_stat->mount_crypt_stat = mount_crypt_stat; | 951 | crypt_stat->mount_crypt_stat = mount_crypt_stat; |
935 | } | 952 | } |
@@ -969,8 +986,10 @@ int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) | |||
969 | if (mount_crypt_stat->global_auth_tok) { | 986 | if (mount_crypt_stat->global_auth_tok) { |
970 | ecryptfs_printk(KERN_DEBUG, "Initializing context for new " | 987 | ecryptfs_printk(KERN_DEBUG, "Initializing context for new " |
971 | "file using mount_crypt_stat\n"); | 988 | "file using mount_crypt_stat\n"); |
972 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); | 989 | crypt_stat->flags |= ECRYPTFS_ENCRYPTED; |
973 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID); | 990 | crypt_stat->flags |= ECRYPTFS_KEY_VALID; |
991 | ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, | ||
992 | mount_crypt_stat); | ||
974 | memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++], | 993 | memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++], |
975 | mount_crypt_stat->global_auth_tok_sig, | 994 | mount_crypt_stat->global_auth_tok_sig, |
976 | ECRYPTFS_SIG_SIZE_HEX); | 995 | ECRYPTFS_SIG_SIZE_HEX); |
@@ -1003,7 +1022,7 @@ int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) | |||
1003 | * | 1022 | * |
1004 | * Returns one if marker found; zero if not found | 1023 | * Returns one if marker found; zero if not found |
1005 | */ | 1024 | */ |
1006 | int contains_ecryptfs_marker(char *data) | 1025 | static int contains_ecryptfs_marker(char *data) |
1007 | { | 1026 | { |
1008 | u32 m_1, m_2; | 1027 | u32 m_1, m_2; |
1009 | 1028 | ||
@@ -1029,7 +1048,8 @@ struct ecryptfs_flag_map_elem { | |||
1029 | /* Add support for additional flags by adding elements here. */ | 1048 | /* Add support for additional flags by adding elements here. */ |
1030 | static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = { | 1049 | static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = { |
1031 | {0x00000001, ECRYPTFS_ENABLE_HMAC}, | 1050 | {0x00000001, ECRYPTFS_ENABLE_HMAC}, |
1032 | {0x00000002, ECRYPTFS_ENCRYPTED} | 1051 | {0x00000002, ECRYPTFS_ENCRYPTED}, |
1052 | {0x00000004, ECRYPTFS_METADATA_IN_XATTR} | ||
1033 | }; | 1053 | }; |
1034 | 1054 | ||
1035 | /** | 1055 | /** |
@@ -1052,11 +1072,9 @@ static int ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat, | |||
1052 | for (i = 0; i < ((sizeof(ecryptfs_flag_map) | 1072 | for (i = 0; i < ((sizeof(ecryptfs_flag_map) |
1053 | / sizeof(struct ecryptfs_flag_map_elem))); i++) | 1073 | / sizeof(struct ecryptfs_flag_map_elem))); i++) |
1054 | if (flags & ecryptfs_flag_map[i].file_flag) { | 1074 | if (flags & ecryptfs_flag_map[i].file_flag) { |
1055 | ECRYPTFS_SET_FLAG(crypt_stat->flags, | 1075 | crypt_stat->flags |= ecryptfs_flag_map[i].local_flag; |
1056 | ecryptfs_flag_map[i].local_flag); | ||
1057 | } else | 1076 | } else |
1058 | ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, | 1077 | crypt_stat->flags &= ~(ecryptfs_flag_map[i].local_flag); |
1059 | ecryptfs_flag_map[i].local_flag); | ||
1060 | /* Version is in top 8 bits of the 32-bit flag vector */ | 1078 | /* Version is in top 8 bits of the 32-bit flag vector */ |
1061 | crypt_stat->file_version = ((flags >> 24) & 0xFF); | 1079 | crypt_stat->file_version = ((flags >> 24) & 0xFF); |
1062 | (*bytes_read) = 4; | 1080 | (*bytes_read) = 4; |
@@ -1093,8 +1111,7 @@ write_ecryptfs_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat, | |||
1093 | 1111 | ||
1094 | for (i = 0; i < ((sizeof(ecryptfs_flag_map) | 1112 | for (i = 0; i < ((sizeof(ecryptfs_flag_map) |
1095 | / sizeof(struct ecryptfs_flag_map_elem))); i++) | 1113 | / sizeof(struct ecryptfs_flag_map_elem))); i++) |
1096 | if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, | 1114 | if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag) |
1097 | ecryptfs_flag_map[i].local_flag)) | ||
1098 | flags |= ecryptfs_flag_map[i].file_flag; | 1115 | flags |= ecryptfs_flag_map[i].file_flag; |
1099 | /* Version is in top 8 bits of the 32-bit flag vector */ | 1116 | /* Version is in top 8 bits of the 32-bit flag vector */ |
1100 | flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000); | 1117 | flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000); |
@@ -1189,8 +1206,8 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code) | |||
1189 | * | 1206 | * |
1190 | * Returns zero on success; non-zero otherwise | 1207 | * Returns zero on success; non-zero otherwise |
1191 | */ | 1208 | */ |
1192 | int ecryptfs_read_header_region(char *data, struct dentry *dentry, | 1209 | static int ecryptfs_read_header_region(char *data, struct dentry *dentry, |
1193 | struct vfsmount *mnt) | 1210 | struct vfsmount *mnt) |
1194 | { | 1211 | { |
1195 | struct file *lower_file; | 1212 | struct file *lower_file; |
1196 | mm_segment_t oldfs; | 1213 | mm_segment_t oldfs; |
@@ -1219,9 +1236,25 @@ out: | |||
1219 | return rc; | 1236 | return rc; |
1220 | } | 1237 | } |
1221 | 1238 | ||
1222 | static void | 1239 | int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry, |
1223 | write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat, | 1240 | struct vfsmount *mnt) |
1224 | size_t *written) | 1241 | { |
1242 | int rc; | ||
1243 | |||
1244 | rc = ecryptfs_read_header_region(data, dentry, mnt); | ||
1245 | if (rc) | ||
1246 | goto out; | ||
1247 | if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) | ||
1248 | rc = -EINVAL; | ||
1249 | out: | ||
1250 | return rc; | ||
1251 | } | ||
1252 | |||
1253 | |||
1254 | void | ||
1255 | ecryptfs_write_header_metadata(char *virt, | ||
1256 | struct ecryptfs_crypt_stat *crypt_stat, | ||
1257 | size_t *written) | ||
1225 | { | 1258 | { |
1226 | u32 header_extent_size; | 1259 | u32 header_extent_size; |
1227 | u16 num_header_extents_at_front; | 1260 | u16 num_header_extents_at_front; |
@@ -1270,9 +1303,9 @@ struct kmem_cache *ecryptfs_header_cache_2; | |||
1270 | * | 1303 | * |
1271 | * Returns zero on success | 1304 | * Returns zero on success |
1272 | */ | 1305 | */ |
1273 | int ecryptfs_write_headers_virt(char *page_virt, | 1306 | static int ecryptfs_write_headers_virt(char *page_virt, size_t *size, |
1274 | struct ecryptfs_crypt_stat *crypt_stat, | 1307 | struct ecryptfs_crypt_stat *crypt_stat, |
1275 | struct dentry *ecryptfs_dentry) | 1308 | struct dentry *ecryptfs_dentry) |
1276 | { | 1309 | { |
1277 | int rc; | 1310 | int rc; |
1278 | size_t written; | 1311 | size_t written; |
@@ -1283,7 +1316,8 @@ int ecryptfs_write_headers_virt(char *page_virt, | |||
1283 | offset += written; | 1316 | offset += written; |
1284 | write_ecryptfs_flags((page_virt + offset), crypt_stat, &written); | 1317 | write_ecryptfs_flags((page_virt + offset), crypt_stat, &written); |
1285 | offset += written; | 1318 | offset += written; |
1286 | write_header_metadata((page_virt + offset), crypt_stat, &written); | 1319 | ecryptfs_write_header_metadata((page_virt + offset), crypt_stat, |
1320 | &written); | ||
1287 | offset += written; | 1321 | offset += written; |
1288 | rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat, | 1322 | rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat, |
1289 | ecryptfs_dentry, &written, | 1323 | ecryptfs_dentry, &written, |
@@ -1291,11 +1325,70 @@ int ecryptfs_write_headers_virt(char *page_virt, | |||
1291 | if (rc) | 1325 | if (rc) |
1292 | ecryptfs_printk(KERN_WARNING, "Error generating key packet " | 1326 | ecryptfs_printk(KERN_WARNING, "Error generating key packet " |
1293 | "set; rc = [%d]\n", rc); | 1327 | "set; rc = [%d]\n", rc); |
1328 | if (size) { | ||
1329 | offset += written; | ||
1330 | *size = offset; | ||
1331 | } | ||
1332 | return rc; | ||
1333 | } | ||
1334 | |||
1335 | static int ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, | ||
1336 | struct file *lower_file, | ||
1337 | char *page_virt) | ||
1338 | { | ||
1339 | mm_segment_t oldfs; | ||
1340 | int current_header_page; | ||
1341 | int header_pages; | ||
1342 | ssize_t size; | ||
1343 | int rc = 0; | ||
1344 | |||
1345 | lower_file->f_pos = 0; | ||
1346 | oldfs = get_fs(); | ||
1347 | set_fs(get_ds()); | ||
1348 | size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE, | ||
1349 | &lower_file->f_pos); | ||
1350 | if (size < 0) { | ||
1351 | rc = (int)size; | ||
1352 | printk(KERN_ERR "Error attempting to write lower page; " | ||
1353 | "rc = [%d]\n", rc); | ||
1354 | set_fs(oldfs); | ||
1355 | goto out; | ||
1356 | } | ||
1357 | header_pages = ((crypt_stat->header_extent_size | ||
1358 | * crypt_stat->num_header_extents_at_front) | ||
1359 | / PAGE_CACHE_SIZE); | ||
1360 | memset(page_virt, 0, PAGE_CACHE_SIZE); | ||
1361 | current_header_page = 1; | ||
1362 | while (current_header_page < header_pages) { | ||
1363 | size = vfs_write(lower_file, (char __user *)page_virt, | ||
1364 | PAGE_CACHE_SIZE, &lower_file->f_pos); | ||
1365 | if (size < 0) { | ||
1366 | rc = (int)size; | ||
1367 | printk(KERN_ERR "Error attempting to write lower page; " | ||
1368 | "rc = [%d]\n", rc); | ||
1369 | set_fs(oldfs); | ||
1370 | goto out; | ||
1371 | } | ||
1372 | current_header_page++; | ||
1373 | } | ||
1374 | set_fs(oldfs); | ||
1375 | out: | ||
1376 | return rc; | ||
1377 | } | ||
1378 | |||
1379 | static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, | ||
1380 | struct ecryptfs_crypt_stat *crypt_stat, | ||
1381 | char *page_virt, size_t size) | ||
1382 | { | ||
1383 | int rc; | ||
1384 | |||
1385 | rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt, | ||
1386 | size, 0); | ||
1294 | return rc; | 1387 | return rc; |
1295 | } | 1388 | } |
1296 | 1389 | ||
1297 | /** | 1390 | /** |
1298 | * ecryptfs_write_headers | 1391 | * ecryptfs_write_metadata |
1299 | * @lower_file: The lower file struct, which was returned from dentry_open | 1392 | * @lower_file: The lower file struct, which was returned from dentry_open |
1300 | * | 1393 | * |
1301 | * Write the file headers out. This will likely involve a userspace | 1394 | * Write the file headers out. This will likely involve a userspace |
@@ -1306,22 +1399,18 @@ int ecryptfs_write_headers_virt(char *page_virt, | |||
1306 | * | 1399 | * |
1307 | * Returns zero on success; non-zero on error | 1400 | * Returns zero on success; non-zero on error |
1308 | */ | 1401 | */ |
1309 | int ecryptfs_write_headers(struct dentry *ecryptfs_dentry, | 1402 | int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, |
1310 | struct file *lower_file) | 1403 | struct file *lower_file) |
1311 | { | 1404 | { |
1312 | mm_segment_t oldfs; | ||
1313 | struct ecryptfs_crypt_stat *crypt_stat; | 1405 | struct ecryptfs_crypt_stat *crypt_stat; |
1314 | char *page_virt; | 1406 | char *page_virt; |
1315 | int current_header_page; | 1407 | size_t size; |
1316 | int header_pages; | ||
1317 | int rc = 0; | 1408 | int rc = 0; |
1318 | 1409 | ||
1319 | crypt_stat = &ecryptfs_inode_to_private( | 1410 | crypt_stat = &ecryptfs_inode_to_private( |
1320 | ecryptfs_dentry->d_inode)->crypt_stat; | 1411 | ecryptfs_dentry->d_inode)->crypt_stat; |
1321 | if (likely(ECRYPTFS_CHECK_FLAG(crypt_stat->flags, | 1412 | if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { |
1322 | ECRYPTFS_ENCRYPTED))) { | 1413 | if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { |
1323 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, | ||
1324 | ECRYPTFS_KEY_VALID)) { | ||
1325 | ecryptfs_printk(KERN_DEBUG, "Key is " | 1414 | ecryptfs_printk(KERN_DEBUG, "Key is " |
1326 | "invalid; bailing out\n"); | 1415 | "invalid; bailing out\n"); |
1327 | rc = -EINVAL; | 1416 | rc = -EINVAL; |
@@ -1334,54 +1423,42 @@ int ecryptfs_write_headers(struct dentry *ecryptfs_dentry, | |||
1334 | goto out; | 1423 | goto out; |
1335 | } | 1424 | } |
1336 | /* Released in this function */ | 1425 | /* Released in this function */ |
1337 | page_virt = kmem_cache_alloc(ecryptfs_header_cache_0, GFP_USER); | 1426 | page_virt = kmem_cache_zalloc(ecryptfs_header_cache_0, GFP_USER); |
1338 | if (!page_virt) { | 1427 | if (!page_virt) { |
1339 | ecryptfs_printk(KERN_ERR, "Out of memory\n"); | 1428 | ecryptfs_printk(KERN_ERR, "Out of memory\n"); |
1340 | rc = -ENOMEM; | 1429 | rc = -ENOMEM; |
1341 | goto out; | 1430 | goto out; |
1342 | } | 1431 | } |
1343 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 1432 | rc = ecryptfs_write_headers_virt(page_virt, &size, crypt_stat, |
1344 | rc = ecryptfs_write_headers_virt(page_virt, crypt_stat, | 1433 | ecryptfs_dentry); |
1345 | ecryptfs_dentry); | ||
1346 | if (unlikely(rc)) { | 1434 | if (unlikely(rc)) { |
1347 | ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n"); | 1435 | ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n"); |
1348 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 1436 | memset(page_virt, 0, PAGE_CACHE_SIZE); |
1349 | goto out_free; | 1437 | goto out_free; |
1350 | } | 1438 | } |
1351 | ecryptfs_printk(KERN_DEBUG, | 1439 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) |
1352 | "Writing key packet set to underlying file\n"); | 1440 | rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, |
1353 | lower_file->f_pos = 0; | 1441 | crypt_stat, page_virt, |
1354 | oldfs = get_fs(); | 1442 | size); |
1355 | set_fs(get_ds()); | 1443 | else |
1356 | ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->" | 1444 | rc = ecryptfs_write_metadata_to_contents(crypt_stat, lower_file, |
1357 | "write() w/ header page; lower_file->f_pos = " | 1445 | page_virt); |
1358 | "[0x%.16x]\n", lower_file->f_pos); | 1446 | if (rc) { |
1359 | lower_file->f_op->write(lower_file, (char __user *)page_virt, | 1447 | printk(KERN_ERR "Error writing metadata out to lower file; " |
1360 | PAGE_CACHE_SIZE, &lower_file->f_pos); | 1448 | "rc = [%d]\n", rc); |
1361 | header_pages = ((crypt_stat->header_extent_size | 1449 | goto out_free; |
1362 | * crypt_stat->num_header_extents_at_front) | ||
1363 | / PAGE_CACHE_SIZE); | ||
1364 | memset(page_virt, 0, PAGE_CACHE_SIZE); | ||
1365 | current_header_page = 1; | ||
1366 | while (current_header_page < header_pages) { | ||
1367 | ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->" | ||
1368 | "write() w/ zero'd page; lower_file->f_pos = " | ||
1369 | "[0x%.16x]\n", lower_file->f_pos); | ||
1370 | lower_file->f_op->write(lower_file, (char __user *)page_virt, | ||
1371 | PAGE_CACHE_SIZE, &lower_file->f_pos); | ||
1372 | current_header_page++; | ||
1373 | } | 1450 | } |
1374 | set_fs(oldfs); | ||
1375 | ecryptfs_printk(KERN_DEBUG, | ||
1376 | "Done writing key packet set to underlying file.\n"); | ||
1377 | out_free: | 1451 | out_free: |
1378 | kmem_cache_free(ecryptfs_header_cache_0, page_virt); | 1452 | kmem_cache_free(ecryptfs_header_cache_0, page_virt); |
1379 | out: | 1453 | out: |
1380 | return rc; | 1454 | return rc; |
1381 | } | 1455 | } |
1382 | 1456 | ||
1457 | #define ECRYPTFS_DONT_VALIDATE_HEADER_SIZE 0 | ||
1458 | #define ECRYPTFS_VALIDATE_HEADER_SIZE 1 | ||
1383 | static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, | 1459 | static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, |
1384 | char *virt, int *bytes_read) | 1460 | char *virt, int *bytes_read, |
1461 | int validate_header_size) | ||
1385 | { | 1462 | { |
1386 | int rc = 0; | 1463 | int rc = 0; |
1387 | u32 header_extent_size; | 1464 | u32 header_extent_size; |
@@ -1396,9 +1473,10 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, | |||
1396 | crypt_stat->num_header_extents_at_front = | 1473 | crypt_stat->num_header_extents_at_front = |
1397 | (int)num_header_extents_at_front; | 1474 | (int)num_header_extents_at_front; |
1398 | (*bytes_read) = 6; | 1475 | (*bytes_read) = 6; |
1399 | if ((crypt_stat->header_extent_size | 1476 | if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE) |
1400 | * crypt_stat->num_header_extents_at_front) | 1477 | && ((crypt_stat->header_extent_size |
1401 | < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) { | 1478 | * crypt_stat->num_header_extents_at_front) |
1479 | < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) { | ||
1402 | rc = -EINVAL; | 1480 | rc = -EINVAL; |
1403 | ecryptfs_printk(KERN_WARNING, "Invalid header extent size: " | 1481 | ecryptfs_printk(KERN_WARNING, "Invalid header extent size: " |
1404 | "[%d]\n", crypt_stat->header_extent_size); | 1482 | "[%d]\n", crypt_stat->header_extent_size); |
@@ -1429,7 +1507,8 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) | |||
1429 | */ | 1507 | */ |
1430 | static int ecryptfs_read_headers_virt(char *page_virt, | 1508 | static int ecryptfs_read_headers_virt(char *page_virt, |
1431 | struct ecryptfs_crypt_stat *crypt_stat, | 1509 | struct ecryptfs_crypt_stat *crypt_stat, |
1432 | struct dentry *ecryptfs_dentry) | 1510 | struct dentry *ecryptfs_dentry, |
1511 | int validate_header_size) | ||
1433 | { | 1512 | { |
1434 | int rc = 0; | 1513 | int rc = 0; |
1435 | int offset; | 1514 | int offset; |
@@ -1463,7 +1542,7 @@ static int ecryptfs_read_headers_virt(char *page_virt, | |||
1463 | offset += bytes_read; | 1542 | offset += bytes_read; |
1464 | if (crypt_stat->file_version >= 1) { | 1543 | if (crypt_stat->file_version >= 1) { |
1465 | rc = parse_header_metadata(crypt_stat, (page_virt + offset), | 1544 | rc = parse_header_metadata(crypt_stat, (page_virt + offset), |
1466 | &bytes_read); | 1545 | &bytes_read, validate_header_size); |
1467 | if (rc) { | 1546 | if (rc) { |
1468 | ecryptfs_printk(KERN_WARNING, "Error reading header " | 1547 | ecryptfs_printk(KERN_WARNING, "Error reading header " |
1469 | "metadata; rc = [%d]\n", rc); | 1548 | "metadata; rc = [%d]\n", rc); |
@@ -1478,12 +1557,60 @@ out: | |||
1478 | } | 1557 | } |
1479 | 1558 | ||
1480 | /** | 1559 | /** |
1481 | * ecryptfs_read_headers | 1560 | * ecryptfs_read_xattr_region |
1561 | * | ||
1562 | * Attempts to read the crypto metadata from the extended attribute | ||
1563 | * region of the lower file. | ||
1564 | */ | ||
1565 | int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry) | ||
1566 | { | ||
1567 | ssize_t size; | ||
1568 | int rc = 0; | ||
1569 | |||
1570 | size = ecryptfs_getxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, | ||
1571 | page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE); | ||
1572 | if (size < 0) { | ||
1573 | printk(KERN_DEBUG "Error attempting to read the [%s] " | ||
1574 | "xattr from the lower file; return value = [%zd]\n", | ||
1575 | ECRYPTFS_XATTR_NAME, size); | ||
1576 | rc = -EINVAL; | ||
1577 | goto out; | ||
1578 | } | ||
1579 | out: | ||
1580 | return rc; | ||
1581 | } | ||
1582 | |||
1583 | int ecryptfs_read_and_validate_xattr_region(char *page_virt, | ||
1584 | struct dentry *ecryptfs_dentry) | ||
1585 | { | ||
1586 | int rc; | ||
1587 | |||
1588 | rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry); | ||
1589 | if (rc) | ||
1590 | goto out; | ||
1591 | if (!contains_ecryptfs_marker(page_virt + ECRYPTFS_FILE_SIZE_BYTES)) { | ||
1592 | printk(KERN_WARNING "Valid data found in [%s] xattr, but " | ||
1593 | "the marker is invalid\n", ECRYPTFS_XATTR_NAME); | ||
1594 | rc = -EINVAL; | ||
1595 | } | ||
1596 | out: | ||
1597 | return rc; | ||
1598 | } | ||
1599 | |||
1600 | /** | ||
1601 | * ecryptfs_read_metadata | ||
1602 | * | ||
1603 | * Common entry point for reading file metadata. From here, we could | ||
1604 | * retrieve the header information from the header region of the file, | ||
1605 | * the xattr region of the file, or some other repostory that is | ||
1606 | * stored separately from the file itself. The current implementation | ||
1607 | * supports retrieving the metadata information from the file contents | ||
1608 | * and from the xattr region. | ||
1482 | * | 1609 | * |
1483 | * Returns zero if valid headers found and parsed; non-zero otherwise | 1610 | * Returns zero if valid headers found and parsed; non-zero otherwise |
1484 | */ | 1611 | */ |
1485 | int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, | 1612 | int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry, |
1486 | struct file *lower_file) | 1613 | struct file *lower_file) |
1487 | { | 1614 | { |
1488 | int rc = 0; | 1615 | int rc = 0; |
1489 | char *page_virt = NULL; | 1616 | char *page_virt = NULL; |
@@ -1491,7 +1618,12 @@ int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, | |||
1491 | ssize_t bytes_read; | 1618 | ssize_t bytes_read; |
1492 | struct ecryptfs_crypt_stat *crypt_stat = | 1619 | struct ecryptfs_crypt_stat *crypt_stat = |
1493 | &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; | 1620 | &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; |
1621 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = | ||
1622 | &ecryptfs_superblock_to_private( | ||
1623 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | ||
1494 | 1624 | ||
1625 | ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, | ||
1626 | mount_crypt_stat); | ||
1495 | /* Read the first page from the underlying file */ | 1627 | /* Read the first page from the underlying file */ |
1496 | page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER); | 1628 | page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER); |
1497 | if (!page_virt) { | 1629 | if (!page_virt) { |
@@ -1512,11 +1644,36 @@ int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, | |||
1512 | goto out; | 1644 | goto out; |
1513 | } | 1645 | } |
1514 | rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, | 1646 | rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, |
1515 | ecryptfs_dentry); | 1647 | ecryptfs_dentry, |
1648 | ECRYPTFS_VALIDATE_HEADER_SIZE); | ||
1516 | if (rc) { | 1649 | if (rc) { |
1517 | ecryptfs_printk(KERN_DEBUG, "Valid eCryptfs headers not " | 1650 | rc = ecryptfs_read_xattr_region(page_virt, |
1518 | "found\n"); | 1651 | ecryptfs_dentry); |
1519 | rc = -EINVAL; | 1652 | if (rc) { |
1653 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " | ||
1654 | "file header region or xattr region\n"); | ||
1655 | rc = -EINVAL; | ||
1656 | goto out; | ||
1657 | } | ||
1658 | rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, | ||
1659 | ecryptfs_dentry, | ||
1660 | ECRYPTFS_DONT_VALIDATE_HEADER_SIZE); | ||
1661 | if (rc) { | ||
1662 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " | ||
1663 | "file xattr region either\n"); | ||
1664 | rc = -EINVAL; | ||
1665 | } | ||
1666 | if (crypt_stat->mount_crypt_stat->flags | ||
1667 | & ECRYPTFS_XATTR_METADATA_ENABLED) { | ||
1668 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; | ||
1669 | } else { | ||
1670 | printk(KERN_WARNING "Attempt to access file with " | ||
1671 | "crypto metadata only in the extended attribute " | ||
1672 | "region, but eCryptfs was mounted without " | ||
1673 | "xattr support enabled. eCryptfs will not treat " | ||
1674 | "this like an encrypted file.\n"); | ||
1675 | rc = -EINVAL; | ||
1676 | } | ||
1520 | } | 1677 | } |
1521 | out: | 1678 | out: |
1522 | if (page_virt) { | 1679 | if (page_virt) { |
diff --git a/fs/ecryptfs/debug.c b/fs/ecryptfs/debug.c index 61f8e894284f..434c7efd80f8 100644 --- a/fs/ecryptfs/debug.c +++ b/fs/ecryptfs/debug.c | |||
@@ -36,7 +36,7 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok) | |||
36 | 36 | ||
37 | ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n", | 37 | ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n", |
38 | auth_tok); | 38 | auth_tok); |
39 | if (ECRYPTFS_CHECK_FLAG(auth_tok->flags, ECRYPTFS_PRIVATE_KEY)) { | 39 | if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) { |
40 | ecryptfs_printk(KERN_DEBUG, " * private key type\n"); | 40 | ecryptfs_printk(KERN_DEBUG, " * private key type\n"); |
41 | ecryptfs_printk(KERN_DEBUG, " * (NO PRIVATE KEY SUPPORT " | 41 | ecryptfs_printk(KERN_DEBUG, " * (NO PRIVATE KEY SUPPORT " |
42 | "IN ECRYPTFS VERSION 0.1)\n"); | 42 | "IN ECRYPTFS VERSION 0.1)\n"); |
@@ -46,8 +46,8 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok) | |||
46 | ECRYPTFS_SALT_SIZE); | 46 | ECRYPTFS_SALT_SIZE); |
47 | salt[ECRYPTFS_SALT_SIZE * 2] = '\0'; | 47 | salt[ECRYPTFS_SALT_SIZE * 2] = '\0'; |
48 | ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt); | 48 | ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt); |
49 | if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags, | 49 | if (auth_tok->token.password.flags & |
50 | ECRYPTFS_PERSISTENT_PASSWORD)) { | 50 | ECRYPTFS_PERSISTENT_PASSWORD) { |
51 | ecryptfs_printk(KERN_DEBUG, " * persistent\n"); | 51 | ecryptfs_printk(KERN_DEBUG, " * persistent\n"); |
52 | } | 52 | } |
53 | memcpy(sig, auth_tok->token.password.signature, | 53 | memcpy(sig, auth_tok->token.password.signature, |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index afb64bdbe6ad..403e3bad1455 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -4,8 +4,10 @@ | |||
4 | * | 4 | * |
5 | * Copyright (C) 1997-2003 Erez Zadok | 5 | * Copyright (C) 1997-2003 Erez Zadok |
6 | * Copyright (C) 2001-2003 Stony Brook University | 6 | * Copyright (C) 2001-2003 Stony Brook University |
7 | * Copyright (C) 2004-2006 International Business Machines Corp. | 7 | * Copyright (C) 2004-2007 International Business Machines Corp. |
8 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 8 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
9 | * Trevor S. Highland <trevor.highland@gmail.com> | ||
10 | * Tyler Hicks <tyhicks@ou.edu> | ||
9 | * | 11 | * |
10 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License as | 13 | * modify it under the terms of the GNU General Public License as |
@@ -31,22 +33,25 @@ | |||
31 | #include <linux/fs_stack.h> | 33 | #include <linux/fs_stack.h> |
32 | #include <linux/namei.h> | 34 | #include <linux/namei.h> |
33 | #include <linux/scatterlist.h> | 35 | #include <linux/scatterlist.h> |
36 | #include <linux/hash.h> | ||
34 | 37 | ||
35 | /* Version verification for shared data structures w/ userspace */ | 38 | /* Version verification for shared data structures w/ userspace */ |
36 | #define ECRYPTFS_VERSION_MAJOR 0x00 | 39 | #define ECRYPTFS_VERSION_MAJOR 0x00 |
37 | #define ECRYPTFS_VERSION_MINOR 0x04 | 40 | #define ECRYPTFS_VERSION_MINOR 0x04 |
38 | #define ECRYPTFS_SUPPORTED_FILE_VERSION 0x01 | 41 | #define ECRYPTFS_SUPPORTED_FILE_VERSION 0x02 |
39 | /* These flags indicate which features are supported by the kernel | 42 | /* These flags indicate which features are supported by the kernel |
40 | * module; userspace tools such as the mount helper read | 43 | * module; userspace tools such as the mount helper read |
41 | * ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine | 44 | * ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine |
42 | * how to behave. */ | 45 | * how to behave. */ |
43 | #define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001 | 46 | #define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001 |
44 | #define ECRYPTFS_VERSIONING_PUBKEY 0x00000002 | 47 | #define ECRYPTFS_VERSIONING_PUBKEY 0x00000002 |
45 | #define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004 | 48 | #define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004 |
46 | #define ECRYPTFS_VERSIONING_POLICY 0x00000008 | 49 | #define ECRYPTFS_VERSIONING_POLICY 0x00000008 |
50 | #define ECRYPTFS_VERSIONING_XATTR 0x00000010 | ||
47 | #define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \ | 51 | #define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \ |
48 | | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH) | 52 | | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \ |
49 | 53 | | ECRYPTFS_VERSIONING_PUBKEY \ | |
54 | | ECRYPTFS_VERSIONING_XATTR) | ||
50 | #define ECRYPTFS_MAX_PASSWORD_LENGTH 64 | 55 | #define ECRYPTFS_MAX_PASSWORD_LENGTH 64 |
51 | #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH | 56 | #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH |
52 | #define ECRYPTFS_SALT_SIZE 8 | 57 | #define ECRYPTFS_SALT_SIZE 8 |
@@ -60,10 +65,25 @@ | |||
60 | #define ECRYPTFS_MAX_KEY_BYTES 64 | 65 | #define ECRYPTFS_MAX_KEY_BYTES 64 |
61 | #define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512 | 66 | #define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512 |
62 | #define ECRYPTFS_DEFAULT_IV_BYTES 16 | 67 | #define ECRYPTFS_DEFAULT_IV_BYTES 16 |
63 | #define ECRYPTFS_FILE_VERSION 0x01 | 68 | #define ECRYPTFS_FILE_VERSION 0x02 |
64 | #define ECRYPTFS_DEFAULT_HEADER_EXTENT_SIZE 8192 | 69 | #define ECRYPTFS_DEFAULT_HEADER_EXTENT_SIZE 8192 |
65 | #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096 | 70 | #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096 |
66 | #define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192 | 71 | #define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192 |
72 | #define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32 | ||
73 | #define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ | ||
74 | #define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3) | ||
75 | #define ECRYPTFS_NLMSG_HELO 100 | ||
76 | #define ECRYPTFS_NLMSG_QUIT 101 | ||
77 | #define ECRYPTFS_NLMSG_REQUEST 102 | ||
78 | #define ECRYPTFS_NLMSG_RESPONSE 103 | ||
79 | #define ECRYPTFS_MAX_PKI_NAME_BYTES 16 | ||
80 | #define ECRYPTFS_DEFAULT_NUM_USERS 4 | ||
81 | #define ECRYPTFS_MAX_NUM_USERS 32768 | ||
82 | #define ECRYPTFS_TRANSPORT_NETLINK 0 | ||
83 | #define ECRYPTFS_TRANSPORT_CONNECTOR 1 | ||
84 | #define ECRYPTFS_TRANSPORT_RELAYFS 2 | ||
85 | #define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_NETLINK | ||
86 | #define ECRYPTFS_XATTR_NAME "user.ecryptfs" | ||
67 | 87 | ||
68 | #define RFC2440_CIPHER_DES3_EDE 0x02 | 88 | #define RFC2440_CIPHER_DES3_EDE 0x02 |
69 | #define RFC2440_CIPHER_CAST_5 0x03 | 89 | #define RFC2440_CIPHER_CAST_5 0x03 |
@@ -74,9 +94,7 @@ | |||
74 | #define RFC2440_CIPHER_TWOFISH 0x0a | 94 | #define RFC2440_CIPHER_TWOFISH 0x0a |
75 | #define RFC2440_CIPHER_CAST_6 0x0b | 95 | #define RFC2440_CIPHER_CAST_6 0x0b |
76 | 96 | ||
77 | #define ECRYPTFS_SET_FLAG(flag_bit_vector, flag) (flag_bit_vector |= (flag)) | 97 | #define RFC2440_CIPHER_RSA 0x01 |
78 | #define ECRYPTFS_CLEAR_FLAG(flag_bit_vector, flag) (flag_bit_vector &= ~(flag)) | ||
79 | #define ECRYPTFS_CHECK_FLAG(flag_bit_vector, flag) (flag_bit_vector & (flag)) | ||
80 | 98 | ||
81 | /** | 99 | /** |
82 | * For convenience, we may need to pass around the encrypted session | 100 | * For convenience, we may need to pass around the encrypted session |
@@ -114,6 +132,14 @@ struct ecryptfs_password { | |||
114 | 132 | ||
115 | enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY}; | 133 | enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY}; |
116 | 134 | ||
135 | struct ecryptfs_private_key { | ||
136 | u32 key_size; | ||
137 | u32 data_len; | ||
138 | u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; | ||
139 | char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1]; | ||
140 | u8 data[]; | ||
141 | }; | ||
142 | |||
117 | /* May be a password or a private key */ | 143 | /* May be a password or a private key */ |
118 | struct ecryptfs_auth_tok { | 144 | struct ecryptfs_auth_tok { |
119 | u16 version; /* 8-bit major and 8-bit minor */ | 145 | u16 version; /* 8-bit major and 8-bit minor */ |
@@ -123,7 +149,7 @@ struct ecryptfs_auth_tok { | |||
123 | u8 reserved[32]; | 149 | u8 reserved[32]; |
124 | union { | 150 | union { |
125 | struct ecryptfs_password password; | 151 | struct ecryptfs_password password; |
126 | /* Private key is in future eCryptfs releases */ | 152 | struct ecryptfs_private_key private_key; |
127 | } token; | 153 | } token; |
128 | } __attribute__ ((packed)); | 154 | } __attribute__ ((packed)); |
129 | 155 | ||
@@ -176,10 +202,14 @@ ecryptfs_get_key_payload_data(struct key *key) | |||
176 | #define ECRYPTFS_FILE_SIZE_BYTES 8 | 202 | #define ECRYPTFS_FILE_SIZE_BYTES 8 |
177 | #define ECRYPTFS_DEFAULT_CIPHER "aes" | 203 | #define ECRYPTFS_DEFAULT_CIPHER "aes" |
178 | #define ECRYPTFS_DEFAULT_KEY_BYTES 16 | 204 | #define ECRYPTFS_DEFAULT_KEY_BYTES 16 |
179 | #define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC | ||
180 | #define ECRYPTFS_DEFAULT_HASH "md5" | 205 | #define ECRYPTFS_DEFAULT_HASH "md5" |
206 | #define ECRYPTFS_TAG_1_PACKET_TYPE 0x01 | ||
181 | #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C | 207 | #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C |
182 | #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED | 208 | #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED |
209 | #define ECRYPTFS_TAG_64_PACKET_TYPE 0x40 | ||
210 | #define ECRYPTFS_TAG_65_PACKET_TYPE 0x41 | ||
211 | #define ECRYPTFS_TAG_66_PACKET_TYPE 0x42 | ||
212 | #define ECRYPTFS_TAG_67_PACKET_TYPE 0x43 | ||
183 | #define MD5_DIGEST_SIZE 16 | 213 | #define MD5_DIGEST_SIZE 16 |
184 | 214 | ||
185 | /** | 215 | /** |
@@ -196,6 +226,8 @@ struct ecryptfs_crypt_stat { | |||
196 | #define ECRYPTFS_ENABLE_HMAC 0x00000020 | 226 | #define ECRYPTFS_ENABLE_HMAC 0x00000020 |
197 | #define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000040 | 227 | #define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000040 |
198 | #define ECRYPTFS_KEY_VALID 0x00000080 | 228 | #define ECRYPTFS_KEY_VALID 0x00000080 |
229 | #define ECRYPTFS_METADATA_IN_XATTR 0x00000100 | ||
230 | #define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200 | ||
199 | u32 flags; | 231 | u32 flags; |
200 | unsigned int file_version; | 232 | unsigned int file_version; |
201 | size_t iv_bytes; | 233 | size_t iv_bytes; |
@@ -242,6 +274,8 @@ struct ecryptfs_dentry_info { | |||
242 | struct ecryptfs_mount_crypt_stat { | 274 | struct ecryptfs_mount_crypt_stat { |
243 | /* Pointers to memory we do not own, do not free these */ | 275 | /* Pointers to memory we do not own, do not free these */ |
244 | #define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001 | 276 | #define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001 |
277 | #define ECRYPTFS_XATTR_METADATA_ENABLED 0x00000002 | ||
278 | #define ECRYPTFS_ENCRYPTED_VIEW_ENABLED 0x00000004 | ||
245 | u32 flags; | 279 | u32 flags; |
246 | struct ecryptfs_auth_tok *global_auth_tok; | 280 | struct ecryptfs_auth_tok *global_auth_tok; |
247 | struct key *global_auth_tok_key; | 281 | struct key *global_auth_tok_key; |
@@ -272,6 +306,33 @@ struct ecryptfs_auth_tok_list_item { | |||
272 | struct ecryptfs_auth_tok auth_tok; | 306 | struct ecryptfs_auth_tok auth_tok; |
273 | }; | 307 | }; |
274 | 308 | ||
309 | struct ecryptfs_message { | ||
310 | u32 index; | ||
311 | u32 data_len; | ||
312 | u8 data[]; | ||
313 | }; | ||
314 | |||
315 | struct ecryptfs_msg_ctx { | ||
316 | #define ECRYPTFS_MSG_CTX_STATE_FREE 0x0001 | ||
317 | #define ECRYPTFS_MSG_CTX_STATE_PENDING 0x0002 | ||
318 | #define ECRYPTFS_MSG_CTX_STATE_DONE 0x0003 | ||
319 | u32 state; | ||
320 | unsigned int index; | ||
321 | unsigned int counter; | ||
322 | struct ecryptfs_message *msg; | ||
323 | struct task_struct *task; | ||
324 | struct list_head node; | ||
325 | struct mutex mux; | ||
326 | }; | ||
327 | |||
328 | extern unsigned int ecryptfs_transport; | ||
329 | |||
330 | struct ecryptfs_daemon_id { | ||
331 | pid_t pid; | ||
332 | uid_t uid; | ||
333 | struct hlist_node id_chain; | ||
334 | }; | ||
335 | |||
275 | static inline struct ecryptfs_file_info * | 336 | static inline struct ecryptfs_file_info * |
276 | ecryptfs_file_to_private(struct file *file) | 337 | ecryptfs_file_to_private(struct file *file) |
277 | { | 338 | { |
@@ -385,13 +446,16 @@ void __ecryptfs_printk(const char *fmt, ...); | |||
385 | 446 | ||
386 | extern const struct file_operations ecryptfs_main_fops; | 447 | extern const struct file_operations ecryptfs_main_fops; |
387 | extern const struct file_operations ecryptfs_dir_fops; | 448 | extern const struct file_operations ecryptfs_dir_fops; |
388 | extern struct inode_operations ecryptfs_main_iops; | 449 | extern const struct inode_operations ecryptfs_main_iops; |
389 | extern struct inode_operations ecryptfs_dir_iops; | 450 | extern const struct inode_operations ecryptfs_dir_iops; |
390 | extern struct inode_operations ecryptfs_symlink_iops; | 451 | extern const struct inode_operations ecryptfs_symlink_iops; |
391 | extern struct super_operations ecryptfs_sops; | 452 | extern const struct super_operations ecryptfs_sops; |
392 | extern struct dentry_operations ecryptfs_dops; | 453 | extern struct dentry_operations ecryptfs_dops; |
393 | extern struct address_space_operations ecryptfs_aops; | 454 | extern struct address_space_operations ecryptfs_aops; |
394 | extern int ecryptfs_verbosity; | 455 | extern int ecryptfs_verbosity; |
456 | extern unsigned int ecryptfs_message_buf_len; | ||
457 | extern signed long ecryptfs_message_wait_timeout; | ||
458 | extern unsigned int ecryptfs_number_of_users; | ||
395 | 459 | ||
396 | extern struct kmem_cache *ecryptfs_auth_tok_list_item_cache; | 460 | extern struct kmem_cache *ecryptfs_auth_tok_list_item_cache; |
397 | extern struct kmem_cache *ecryptfs_file_info_cache; | 461 | extern struct kmem_cache *ecryptfs_file_info_cache; |
@@ -401,7 +465,9 @@ extern struct kmem_cache *ecryptfs_sb_info_cache; | |||
401 | extern struct kmem_cache *ecryptfs_header_cache_0; | 465 | extern struct kmem_cache *ecryptfs_header_cache_0; |
402 | extern struct kmem_cache *ecryptfs_header_cache_1; | 466 | extern struct kmem_cache *ecryptfs_header_cache_1; |
403 | extern struct kmem_cache *ecryptfs_header_cache_2; | 467 | extern struct kmem_cache *ecryptfs_header_cache_2; |
468 | extern struct kmem_cache *ecryptfs_xattr_cache; | ||
404 | extern struct kmem_cache *ecryptfs_lower_page_cache; | 469 | extern struct kmem_cache *ecryptfs_lower_page_cache; |
470 | extern struct kmem_cache *ecryptfs_key_record_cache; | ||
405 | 471 | ||
406 | int ecryptfs_interpose(struct dentry *hidden_dentry, | 472 | int ecryptfs_interpose(struct dentry *hidden_dentry, |
407 | struct dentry *this_dentry, struct super_block *sb, | 473 | struct dentry *this_dentry, struct super_block *sb, |
@@ -427,9 +493,13 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); | |||
427 | int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, | 493 | int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, |
428 | char *cipher_name, | 494 | char *cipher_name, |
429 | char *chaining_modifier); | 495 | char *chaining_modifier); |
430 | int ecryptfs_write_inode_size_to_header(struct file *lower_file, | 496 | #define ECRYPTFS_LOWER_I_MUTEX_NOT_HELD 0 |
431 | struct inode *lower_inode, | 497 | #define ECRYPTFS_LOWER_I_MUTEX_HELD 1 |
432 | struct inode *inode); | 498 | int ecryptfs_write_inode_size_to_metadata(struct file *lower_file, |
499 | struct inode *lower_inode, | ||
500 | struct inode *inode, | ||
501 | struct dentry *ecryptfs_dentry, | ||
502 | int lower_i_mutex_held); | ||
433 | int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, | 503 | int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, |
434 | struct file *lower_file, | 504 | struct file *lower_file, |
435 | unsigned long lower_page_index, int byte_offset, | 505 | unsigned long lower_page_index, int byte_offset, |
@@ -442,26 +512,20 @@ int ecryptfs_copy_page_to_lower(struct page *page, struct inode *lower_inode, | |||
442 | struct file *lower_file); | 512 | struct file *lower_file); |
443 | int ecryptfs_do_readpage(struct file *file, struct page *page, | 513 | int ecryptfs_do_readpage(struct file *file, struct page *page, |
444 | pgoff_t lower_page_index); | 514 | pgoff_t lower_page_index); |
445 | int ecryptfs_grab_and_map_lower_page(struct page **lower_page, | ||
446 | char **lower_virt, | ||
447 | struct inode *lower_inode, | ||
448 | unsigned long lower_page_index); | ||
449 | int ecryptfs_writepage_and_release_lower_page(struct page *lower_page, | 515 | int ecryptfs_writepage_and_release_lower_page(struct page *lower_page, |
450 | struct inode *lower_inode, | 516 | struct inode *lower_inode, |
451 | struct writeback_control *wbc); | 517 | struct writeback_control *wbc); |
452 | int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx); | 518 | int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx); |
453 | int ecryptfs_decrypt_page(struct file *file, struct page *page); | 519 | int ecryptfs_decrypt_page(struct file *file, struct page *page); |
454 | int ecryptfs_write_headers(struct dentry *ecryptfs_dentry, | 520 | int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, |
521 | struct file *lower_file); | ||
522 | int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry, | ||
455 | struct file *lower_file); | 523 | struct file *lower_file); |
456 | int ecryptfs_write_headers_virt(char *page_virt, | ||
457 | struct ecryptfs_crypt_stat *crypt_stat, | ||
458 | struct dentry *ecryptfs_dentry); | ||
459 | int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, | ||
460 | struct file *lower_file); | ||
461 | int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry); | 524 | int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry); |
462 | int contains_ecryptfs_marker(char *data); | 525 | int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry, |
463 | int ecryptfs_read_header_region(char *data, struct dentry *dentry, | 526 | struct vfsmount *mnt); |
464 | struct vfsmount *mnt); | 527 | int ecryptfs_read_and_validate_xattr_region(char *page_virt, |
528 | struct dentry *ecryptfs_dentry); | ||
465 | u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat); | 529 | u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat); |
466 | int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code); | 530 | int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code); |
467 | void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat); | 531 | void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat); |
@@ -484,5 +548,37 @@ int ecryptfs_open_lower_file(struct file **lower_file, | |||
484 | struct dentry *lower_dentry, | 548 | struct dentry *lower_dentry, |
485 | struct vfsmount *lower_mnt, int flags); | 549 | struct vfsmount *lower_mnt, int flags); |
486 | int ecryptfs_close_lower_file(struct file *lower_file); | 550 | int ecryptfs_close_lower_file(struct file *lower_file); |
551 | ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, | ||
552 | size_t size); | ||
553 | int | ||
554 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | ||
555 | size_t size, int flags); | ||
556 | int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry); | ||
557 | int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid); | ||
558 | int ecryptfs_process_quit(uid_t uid, pid_t pid); | ||
559 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid, | ||
560 | pid_t pid, u32 seq); | ||
561 | int ecryptfs_send_message(unsigned int transport, char *data, int data_len, | ||
562 | struct ecryptfs_msg_ctx **msg_ctx); | ||
563 | int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, | ||
564 | struct ecryptfs_message **emsg); | ||
565 | int ecryptfs_init_messaging(unsigned int transport); | ||
566 | void ecryptfs_release_messaging(unsigned int transport); | ||
567 | |||
568 | int ecryptfs_send_netlink(char *data, int data_len, | ||
569 | struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type, | ||
570 | u16 msg_flags, pid_t daemon_pid); | ||
571 | int ecryptfs_init_netlink(void); | ||
572 | void ecryptfs_release_netlink(void); | ||
573 | |||
574 | int ecryptfs_send_connector(char *data, int data_len, | ||
575 | struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type, | ||
576 | u16 msg_flags, pid_t daemon_pid); | ||
577 | int ecryptfs_init_connector(void); | ||
578 | void ecryptfs_release_connector(void); | ||
579 | void | ||
580 | ecryptfs_write_header_metadata(char *virt, | ||
581 | struct ecryptfs_crypt_stat *crypt_stat, | ||
582 | size_t *written); | ||
487 | 583 | ||
488 | #endif /* #ifndef ECRYPTFS_KERNEL_H */ | 584 | #endif /* #ifndef ECRYPTFS_KERNEL_H */ |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index c5a2e5298f15..bd969adf70d7 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-2004 Erez Zadok | 4 | * Copyright (C) 1997-2004 Erez Zadok |
5 | * Copyright (C) 2001-2004 Stony Brook University | 5 | * Copyright (C) 2001-2004 Stony Brook University |
6 | * Copyright (C) 2004-2006 International Business Machines Corp. | 6 | * Copyright (C) 2004-2007 International Business Machines Corp. |
7 | * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> | 7 | * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> |
8 | * Michael C. Thompson <mcthomps@us.ibm.com> | 8 | * Michael C. Thompson <mcthomps@us.ibm.com> |
9 | * | 9 | * |
@@ -250,8 +250,19 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
250 | struct ecryptfs_file_info *file_info; | 250 | struct ecryptfs_file_info *file_info; |
251 | int lower_flags; | 251 | int lower_flags; |
252 | 252 | ||
253 | mount_crypt_stat = &ecryptfs_superblock_to_private( | ||
254 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | ||
255 | if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) | ||
256 | && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR) | ||
257 | || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC) | ||
258 | || (file->f_flags & O_APPEND))) { | ||
259 | printk(KERN_WARNING "Mount has encrypted view enabled; " | ||
260 | "files may only be read\n"); | ||
261 | rc = -EPERM; | ||
262 | goto out; | ||
263 | } | ||
253 | /* Released in ecryptfs_release or end of function if failure */ | 264 | /* Released in ecryptfs_release or end of function if failure */ |
254 | file_info = kmem_cache_alloc(ecryptfs_file_info_cache, GFP_KERNEL); | 265 | file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); |
255 | ecryptfs_set_file_private(file, file_info); | 266 | ecryptfs_set_file_private(file, file_info); |
256 | if (!file_info) { | 267 | if (!file_info) { |
257 | ecryptfs_printk(KERN_ERR, | 268 | ecryptfs_printk(KERN_ERR, |
@@ -259,17 +270,14 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
259 | rc = -ENOMEM; | 270 | rc = -ENOMEM; |
260 | goto out; | 271 | goto out; |
261 | } | 272 | } |
262 | memset(file_info, 0, sizeof(*file_info)); | ||
263 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); | 273 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); |
264 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; | 274 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; |
265 | mount_crypt_stat = &ecryptfs_superblock_to_private( | ||
266 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | ||
267 | mutex_lock(&crypt_stat->cs_mutex); | 275 | mutex_lock(&crypt_stat->cs_mutex); |
268 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) { | 276 | if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) { |
269 | ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n"); | 277 | ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n"); |
270 | /* Policy code enabled in future release */ | 278 | /* Policy code enabled in future release */ |
271 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED); | 279 | crypt_stat->flags |= ECRYPTFS_POLICY_APPLIED; |
272 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); | 280 | crypt_stat->flags |= ECRYPTFS_ENCRYPTED; |
273 | } | 281 | } |
274 | mutex_unlock(&crypt_stat->cs_mutex); | 282 | mutex_unlock(&crypt_stat->cs_mutex); |
275 | lower_flags = file->f_flags; | 283 | lower_flags = file->f_flags; |
@@ -289,31 +297,14 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
289 | lower_inode = lower_dentry->d_inode; | 297 | lower_inode = lower_dentry->d_inode; |
290 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { | 298 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { |
291 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); | 299 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); |
292 | ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); | 300 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); |
293 | rc = 0; | 301 | rc = 0; |
294 | goto out; | 302 | goto out; |
295 | } | 303 | } |
296 | mutex_lock(&crypt_stat->cs_mutex); | 304 | mutex_lock(&crypt_stat->cs_mutex); |
297 | if (i_size_read(lower_inode) < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) { | 305 | if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) |
298 | if (!(mount_crypt_stat->flags | 306 | || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { |
299 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { | 307 | rc = ecryptfs_read_metadata(ecryptfs_dentry, lower_file); |
300 | rc = -EIO; | ||
301 | printk(KERN_WARNING "Attempt to read file that is " | ||
302 | "not in a valid eCryptfs format, and plaintext " | ||
303 | "passthrough mode is not enabled; returning " | ||
304 | "-EIO\n"); | ||
305 | mutex_unlock(&crypt_stat->cs_mutex); | ||
306 | goto out_puts; | ||
307 | } | ||
308 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | ||
309 | rc = 0; | ||
310 | mutex_unlock(&crypt_stat->cs_mutex); | ||
311 | goto out; | ||
312 | } else if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, | ||
313 | ECRYPTFS_POLICY_APPLIED) | ||
314 | || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, | ||
315 | ECRYPTFS_KEY_VALID)) { | ||
316 | rc = ecryptfs_read_headers(ecryptfs_dentry, lower_file); | ||
317 | if (rc) { | 308 | if (rc) { |
318 | ecryptfs_printk(KERN_DEBUG, | 309 | ecryptfs_printk(KERN_DEBUG, |
319 | "Valid headers not found\n"); | 310 | "Valid headers not found\n"); |
@@ -327,9 +318,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
327 | mutex_unlock(&crypt_stat->cs_mutex); | 318 | mutex_unlock(&crypt_stat->cs_mutex); |
328 | goto out_puts; | 319 | goto out_puts; |
329 | } | 320 | } |
330 | ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, | ||
331 | ECRYPTFS_ENCRYPTED); | ||
332 | rc = 0; | 321 | rc = 0; |
322 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | ||
333 | mutex_unlock(&crypt_stat->cs_mutex); | 323 | mutex_unlock(&crypt_stat->cs_mutex); |
334 | goto out; | 324 | goto out; |
335 | } | 325 | } |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 11f5e5076aef..9fa7e0b27a96 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-2004 Erez Zadok | 4 | * Copyright (C) 1997-2004 Erez Zadok |
5 | * Copyright (C) 2001-2004 Stony Brook University | 5 | * Copyright (C) 2001-2004 Stony Brook University |
6 | * Copyright (C) 2004-2006 International Business Machines Corp. | 6 | * Copyright (C) 2004-2007 International Business Machines Corp. |
7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
8 | * Michael C. Thompsion <mcthomps@us.ibm.com> | 8 | * Michael C. Thompsion <mcthomps@us.ibm.com> |
9 | * | 9 | * |
@@ -161,17 +161,17 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file, | |||
161 | ecryptfs_set_file_lower(&fake_file, lower_file); | 161 | ecryptfs_set_file_lower(&fake_file, lower_file); |
162 | rc = ecryptfs_fill_zeros(&fake_file, 1); | 162 | rc = ecryptfs_fill_zeros(&fake_file, 1); |
163 | if (rc) { | 163 | if (rc) { |
164 | ECRYPTFS_SET_FLAG( | 164 | ecryptfs_inode_to_private(inode)->crypt_stat.flags |= |
165 | ecryptfs_inode_to_private(inode)->crypt_stat.flags, | 165 | ECRYPTFS_SECURITY_WARNING; |
166 | ECRYPTFS_SECURITY_WARNING); | ||
167 | ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros " | 166 | ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros " |
168 | "in file; rc = [%d]\n", rc); | 167 | "in file; rc = [%d]\n", rc); |
169 | goto out; | 168 | goto out; |
170 | } | 169 | } |
171 | i_size_write(inode, 0); | 170 | i_size_write(inode, 0); |
172 | ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode); | 171 | ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode, |
173 | ECRYPTFS_SET_FLAG(ecryptfs_inode_to_private(inode)->crypt_stat.flags, | 172 | ecryptfs_dentry, |
174 | ECRYPTFS_NEW_FILE); | 173 | ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); |
174 | ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE; | ||
175 | out: | 175 | out: |
176 | return rc; | 176 | return rc; |
177 | } | 177 | } |
@@ -199,7 +199,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
199 | lower_dentry->d_name.name); | 199 | lower_dentry->d_name.name); |
200 | inode = ecryptfs_dentry->d_inode; | 200 | inode = ecryptfs_dentry->d_inode; |
201 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; | 201 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; |
202 | lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR; | 202 | lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR; |
203 | #if BITS_PER_LONG != 32 | 203 | #if BITS_PER_LONG != 32 |
204 | lower_flags |= O_LARGEFILE; | 204 | lower_flags |= O_LARGEFILE; |
205 | #endif | 205 | #endif |
@@ -214,10 +214,10 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
214 | lower_inode = lower_dentry->d_inode; | 214 | lower_inode = lower_dentry->d_inode; |
215 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { | 215 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { |
216 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); | 216 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); |
217 | ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); | 217 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); |
218 | goto out_fput; | 218 | goto out_fput; |
219 | } | 219 | } |
220 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE); | 220 | crypt_stat->flags |= ECRYPTFS_NEW_FILE; |
221 | ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); | 221 | ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); |
222 | rc = ecryptfs_new_file_context(ecryptfs_dentry); | 222 | rc = ecryptfs_new_file_context(ecryptfs_dentry); |
223 | if (rc) { | 223 | if (rc) { |
@@ -225,7 +225,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
225 | "context\n"); | 225 | "context\n"); |
226 | goto out_fput; | 226 | goto out_fput; |
227 | } | 227 | } |
228 | rc = ecryptfs_write_headers(ecryptfs_dentry, lower_file); | 228 | rc = ecryptfs_write_metadata(ecryptfs_dentry, lower_file); |
229 | if (rc) { | 229 | if (rc) { |
230 | ecryptfs_printk(KERN_DEBUG, "Error writing headers\n"); | 230 | ecryptfs_printk(KERN_DEBUG, "Error writing headers\n"); |
231 | goto out_fput; | 231 | goto out_fput; |
@@ -287,6 +287,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
287 | char *encoded_name; | 287 | char *encoded_name; |
288 | unsigned int encoded_namelen; | 288 | unsigned int encoded_namelen; |
289 | struct ecryptfs_crypt_stat *crypt_stat = NULL; | 289 | struct ecryptfs_crypt_stat *crypt_stat = NULL; |
290 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
290 | char *page_virt = NULL; | 291 | char *page_virt = NULL; |
291 | struct inode *lower_inode; | 292 | struct inode *lower_inode; |
292 | u64 file_size; | 293 | u64 file_size; |
@@ -361,34 +362,44 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
361 | goto out; | 362 | goto out; |
362 | } | 363 | } |
363 | /* Released in this function */ | 364 | /* Released in this function */ |
364 | page_virt = | 365 | page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, |
365 | (char *)kmem_cache_alloc(ecryptfs_header_cache_2, | 366 | GFP_USER); |
366 | GFP_USER); | ||
367 | if (!page_virt) { | 367 | if (!page_virt) { |
368 | rc = -ENOMEM; | 368 | rc = -ENOMEM; |
369 | ecryptfs_printk(KERN_ERR, | 369 | ecryptfs_printk(KERN_ERR, |
370 | "Cannot ecryptfs_kmalloc a page\n"); | 370 | "Cannot ecryptfs_kmalloc a page\n"); |
371 | goto out_dput; | 371 | goto out_dput; |
372 | } | 372 | } |
373 | memset(page_virt, 0, PAGE_CACHE_SIZE); | ||
374 | rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt); | ||
375 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 373 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
376 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) | 374 | if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) |
377 | ecryptfs_set_default_sizes(crypt_stat); | 375 | ecryptfs_set_default_sizes(crypt_stat); |
376 | rc = ecryptfs_read_and_validate_header_region(page_virt, lower_dentry, | ||
377 | nd->mnt); | ||
378 | if (rc) { | 378 | if (rc) { |
379 | rc = 0; | 379 | rc = ecryptfs_read_and_validate_xattr_region(page_virt, dentry); |
380 | ecryptfs_printk(KERN_WARNING, "Error reading header region;" | 380 | if (rc) { |
381 | " assuming unencrypted\n"); | 381 | printk(KERN_DEBUG "Valid metadata not found in header " |
382 | } else { | 382 | "region or xattr region; treating file as " |
383 | if (!contains_ecryptfs_marker(page_virt | 383 | "unencrypted\n"); |
384 | + ECRYPTFS_FILE_SIZE_BYTES)) { | 384 | rc = 0; |
385 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 385 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
386 | goto out; | 386 | goto out; |
387 | } | 387 | } |
388 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; | ||
389 | } | ||
390 | mount_crypt_stat = &ecryptfs_superblock_to_private( | ||
391 | dentry->d_sb)->mount_crypt_stat; | ||
392 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { | ||
393 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | ||
394 | file_size = (crypt_stat->header_extent_size | ||
395 | + i_size_read(lower_dentry->d_inode)); | ||
396 | else | ||
397 | file_size = i_size_read(lower_dentry->d_inode); | ||
398 | } else { | ||
388 | memcpy(&file_size, page_virt, sizeof(file_size)); | 399 | memcpy(&file_size, page_virt, sizeof(file_size)); |
389 | file_size = be64_to_cpu(file_size); | 400 | file_size = be64_to_cpu(file_size); |
390 | i_size_write(dentry->d_inode, (loff_t)file_size); | ||
391 | } | 401 | } |
402 | i_size_write(dentry->d_inode, (loff_t)file_size); | ||
392 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 403 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
393 | goto out; | 404 | goto out; |
394 | 405 | ||
@@ -782,20 +793,26 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
782 | goto out_fput; | 793 | goto out_fput; |
783 | } | 794 | } |
784 | i_size_write(inode, new_length); | 795 | i_size_write(inode, new_length); |
785 | rc = ecryptfs_write_inode_size_to_header(lower_file, | 796 | rc = ecryptfs_write_inode_size_to_metadata( |
786 | lower_dentry->d_inode, | 797 | lower_file, lower_dentry->d_inode, inode, dentry, |
787 | inode); | 798 | ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); |
788 | if (rc) { | 799 | if (rc) { |
789 | ecryptfs_printk(KERN_ERR, | 800 | printk(KERN_ERR "Problem with " |
790 | "Problem with ecryptfs_write" | 801 | "ecryptfs_write_inode_size_to_metadata; " |
791 | "_inode_size\n"); | 802 | "rc = [%d]\n", rc); |
792 | goto out_fput; | 803 | goto out_fput; |
793 | } | 804 | } |
794 | } else { /* new_length < i_size_read(inode) */ | 805 | } else { /* new_length < i_size_read(inode) */ |
795 | vmtruncate(inode, new_length); | 806 | vmtruncate(inode, new_length); |
796 | ecryptfs_write_inode_size_to_header(lower_file, | 807 | rc = ecryptfs_write_inode_size_to_metadata( |
797 | lower_dentry->d_inode, | 808 | lower_file, lower_dentry->d_inode, inode, dentry, |
798 | inode); | 809 | ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); |
810 | if (rc) { | ||
811 | printk(KERN_ERR "Problem with " | ||
812 | "ecryptfs_write_inode_size_to_metadata; " | ||
813 | "rc = [%d]\n", rc); | ||
814 | goto out_fput; | ||
815 | } | ||
799 | /* We are reducing the size of the ecryptfs file, and need to | 816 | /* We are reducing the size of the ecryptfs file, and need to |
800 | * know if we need to reduce the size of the lower file. */ | 817 | * know if we need to reduce the size of the lower file. */ |
801 | lower_size_before_truncate = | 818 | lower_size_before_truncate = |
@@ -882,7 +899,7 @@ out: | |||
882 | return rc; | 899 | return rc; |
883 | } | 900 | } |
884 | 901 | ||
885 | static int | 902 | int |
886 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 903 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
887 | size_t size, int flags) | 904 | size_t size, int flags) |
888 | { | 905 | { |
@@ -902,7 +919,7 @@ out: | |||
902 | return rc; | 919 | return rc; |
903 | } | 920 | } |
904 | 921 | ||
905 | static ssize_t | 922 | ssize_t |
906 | ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, | 923 | ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, |
907 | size_t size) | 924 | size_t size) |
908 | { | 925 | { |
@@ -972,7 +989,7 @@ int ecryptfs_inode_set(struct inode *inode, void *lower_inode) | |||
972 | return 0; | 989 | return 0; |
973 | } | 990 | } |
974 | 991 | ||
975 | struct inode_operations ecryptfs_symlink_iops = { | 992 | const struct inode_operations ecryptfs_symlink_iops = { |
976 | .readlink = ecryptfs_readlink, | 993 | .readlink = ecryptfs_readlink, |
977 | .follow_link = ecryptfs_follow_link, | 994 | .follow_link = ecryptfs_follow_link, |
978 | .put_link = ecryptfs_put_link, | 995 | .put_link = ecryptfs_put_link, |
@@ -984,7 +1001,7 @@ struct inode_operations ecryptfs_symlink_iops = { | |||
984 | .removexattr = ecryptfs_removexattr | 1001 | .removexattr = ecryptfs_removexattr |
985 | }; | 1002 | }; |
986 | 1003 | ||
987 | struct inode_operations ecryptfs_dir_iops = { | 1004 | const struct inode_operations ecryptfs_dir_iops = { |
988 | .create = ecryptfs_create, | 1005 | .create = ecryptfs_create, |
989 | .lookup = ecryptfs_lookup, | 1006 | .lookup = ecryptfs_lookup, |
990 | .link = ecryptfs_link, | 1007 | .link = ecryptfs_link, |
@@ -1002,7 +1019,7 @@ struct inode_operations ecryptfs_dir_iops = { | |||
1002 | .removexattr = ecryptfs_removexattr | 1019 | .removexattr = ecryptfs_removexattr |
1003 | }; | 1020 | }; |
1004 | 1021 | ||
1005 | struct inode_operations ecryptfs_main_iops = { | 1022 | const struct inode_operations ecryptfs_main_iops = { |
1006 | .permission = ecryptfs_permission, | 1023 | .permission = ecryptfs_permission, |
1007 | .setattr = ecryptfs_setattr, | 1024 | .setattr = ecryptfs_setattr, |
1008 | .setxattr = ecryptfs_setxattr, | 1025 | .setxattr = ecryptfs_setxattr, |
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 745c0f1bfbbd..b550dea8eee6 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (C) 2004-2006 International Business Machines Corp. | 7 | * Copyright (C) 2004-2006 International Business Machines Corp. |
8 | * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> | 8 | * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> |
9 | * Michael C. Thompson <mcthomps@us.ibm.com> | 9 | * Michael C. Thompson <mcthomps@us.ibm.com> |
10 | * Trevor S. Highland <trevor.highland@gmail.com> | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License as | 13 | * modify it under the terms of the GNU General Public License as |
@@ -25,7 +26,6 @@ | |||
25 | */ | 26 | */ |
26 | 27 | ||
27 | #include <linux/string.h> | 28 | #include <linux/string.h> |
28 | #include <linux/sched.h> | ||
29 | #include <linux/syscalls.h> | 29 | #include <linux/syscalls.h> |
30 | #include <linux/pagemap.h> | 30 | #include <linux/pagemap.h> |
31 | #include <linux/key.h> | 31 | #include <linux/key.h> |
@@ -64,26 +64,6 @@ int process_request_key_err(long err_code) | |||
64 | return rc; | 64 | return rc; |
65 | } | 65 | } |
66 | 66 | ||
67 | static void wipe_auth_tok_list(struct list_head *auth_tok_list_head) | ||
68 | { | ||
69 | struct list_head *walker; | ||
70 | struct ecryptfs_auth_tok_list_item *auth_tok_list_item; | ||
71 | |||
72 | walker = auth_tok_list_head->next; | ||
73 | while (walker != auth_tok_list_head) { | ||
74 | auth_tok_list_item = | ||
75 | list_entry(walker, struct ecryptfs_auth_tok_list_item, | ||
76 | list); | ||
77 | walker = auth_tok_list_item->list.next; | ||
78 | memset(auth_tok_list_item, 0, | ||
79 | sizeof(struct ecryptfs_auth_tok_list_item)); | ||
80 | kmem_cache_free(ecryptfs_auth_tok_list_item_cache, | ||
81 | auth_tok_list_item); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | struct kmem_cache *ecryptfs_auth_tok_list_item_cache; | ||
86 | |||
87 | /** | 67 | /** |
88 | * parse_packet_length | 68 | * parse_packet_length |
89 | * @data: Pointer to memory containing length at offset | 69 | * @data: Pointer to memory containing length at offset |
@@ -102,12 +82,12 @@ static int parse_packet_length(unsigned char *data, size_t *size, | |||
102 | (*size) = 0; | 82 | (*size) = 0; |
103 | if (data[0] < 192) { | 83 | if (data[0] < 192) { |
104 | /* One-byte length */ | 84 | /* One-byte length */ |
105 | (*size) = data[0]; | 85 | (*size) = (unsigned char)data[0]; |
106 | (*length_size) = 1; | 86 | (*length_size) = 1; |
107 | } else if (data[0] < 224) { | 87 | } else if (data[0] < 224) { |
108 | /* Two-byte length */ | 88 | /* Two-byte length */ |
109 | (*size) = ((data[0] - 192) * 256); | 89 | (*size) = (((unsigned char)(data[0]) - 192) * 256); |
110 | (*size) += (data[1] + 192); | 90 | (*size) += ((unsigned char)(data[1]) + 192); |
111 | (*length_size) = 2; | 91 | (*length_size) = 2; |
112 | } else if (data[0] == 255) { | 92 | } else if (data[0] == 255) { |
113 | /* Five-byte length; we're not supposed to see this */ | 93 | /* Five-byte length; we're not supposed to see this */ |
@@ -154,6 +134,499 @@ static int write_packet_length(char *dest, size_t size, | |||
154 | return rc; | 134 | return rc; |
155 | } | 135 | } |
156 | 136 | ||
137 | static int | ||
138 | write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key, | ||
139 | char **packet, size_t *packet_len) | ||
140 | { | ||
141 | size_t i = 0; | ||
142 | size_t data_len; | ||
143 | size_t packet_size_len; | ||
144 | char *message; | ||
145 | int rc; | ||
146 | |||
147 | /* | ||
148 | * ***** TAG 64 Packet Format ***** | ||
149 | * | Content Type | 1 byte | | ||
150 | * | Key Identifier Size | 1 or 2 bytes | | ||
151 | * | Key Identifier | arbitrary | | ||
152 | * | Encrypted File Encryption Key Size | 1 or 2 bytes | | ||
153 | * | Encrypted File Encryption Key | arbitrary | | ||
154 | */ | ||
155 | data_len = (5 + ECRYPTFS_SIG_SIZE_HEX | ||
156 | + session_key->encrypted_key_size); | ||
157 | *packet = kmalloc(data_len, GFP_KERNEL); | ||
158 | message = *packet; | ||
159 | if (!message) { | ||
160 | ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); | ||
161 | rc = -ENOMEM; | ||
162 | goto out; | ||
163 | } | ||
164 | message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE; | ||
165 | rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX, | ||
166 | &packet_size_len); | ||
167 | if (rc) { | ||
168 | ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet " | ||
169 | "header; cannot generate packet length\n"); | ||
170 | goto out; | ||
171 | } | ||
172 | i += packet_size_len; | ||
173 | memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX); | ||
174 | i += ECRYPTFS_SIG_SIZE_HEX; | ||
175 | rc = write_packet_length(&message[i], session_key->encrypted_key_size, | ||
176 | &packet_size_len); | ||
177 | if (rc) { | ||
178 | ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet " | ||
179 | "header; cannot generate packet length\n"); | ||
180 | goto out; | ||
181 | } | ||
182 | i += packet_size_len; | ||
183 | memcpy(&message[i], session_key->encrypted_key, | ||
184 | session_key->encrypted_key_size); | ||
185 | i += session_key->encrypted_key_size; | ||
186 | *packet_len = i; | ||
187 | out: | ||
188 | return rc; | ||
189 | } | ||
190 | |||
191 | static int | ||
192 | parse_tag_65_packet(struct ecryptfs_session_key *session_key, u16 *cipher_code, | ||
193 | struct ecryptfs_message *msg) | ||
194 | { | ||
195 | size_t i = 0; | ||
196 | char *data; | ||
197 | size_t data_len; | ||
198 | size_t m_size; | ||
199 | size_t message_len; | ||
200 | u16 checksum = 0; | ||
201 | u16 expected_checksum = 0; | ||
202 | int rc; | ||
203 | |||
204 | /* | ||
205 | * ***** TAG 65 Packet Format ***** | ||
206 | * | Content Type | 1 byte | | ||
207 | * | Status Indicator | 1 byte | | ||
208 | * | File Encryption Key Size | 1 or 2 bytes | | ||
209 | * | File Encryption Key | arbitrary | | ||
210 | */ | ||
211 | message_len = msg->data_len; | ||
212 | data = msg->data; | ||
213 | if (message_len < 4) { | ||
214 | rc = -EIO; | ||
215 | goto out; | ||
216 | } | ||
217 | if (data[i++] != ECRYPTFS_TAG_65_PACKET_TYPE) { | ||
218 | ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_65\n"); | ||
219 | rc = -EIO; | ||
220 | goto out; | ||
221 | } | ||
222 | if (data[i++]) { | ||
223 | ecryptfs_printk(KERN_ERR, "Status indicator has non-zero value " | ||
224 | "[%d]\n", data[i-1]); | ||
225 | rc = -EIO; | ||
226 | goto out; | ||
227 | } | ||
228 | rc = parse_packet_length(&data[i], &m_size, &data_len); | ||
229 | if (rc) { | ||
230 | ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " | ||
231 | "rc = [%d]\n", rc); | ||
232 | goto out; | ||
233 | } | ||
234 | i += data_len; | ||
235 | if (message_len < (i + m_size)) { | ||
236 | ecryptfs_printk(KERN_ERR, "The received netlink message is " | ||
237 | "shorter than expected\n"); | ||
238 | rc = -EIO; | ||
239 | goto out; | ||
240 | } | ||
241 | if (m_size < 3) { | ||
242 | ecryptfs_printk(KERN_ERR, | ||
243 | "The decrypted key is not long enough to " | ||
244 | "include a cipher code and checksum\n"); | ||
245 | rc = -EIO; | ||
246 | goto out; | ||
247 | } | ||
248 | *cipher_code = data[i++]; | ||
249 | /* The decrypted key includes 1 byte cipher code and 2 byte checksum */ | ||
250 | session_key->decrypted_key_size = m_size - 3; | ||
251 | if (session_key->decrypted_key_size > ECRYPTFS_MAX_KEY_BYTES) { | ||
252 | ecryptfs_printk(KERN_ERR, "key_size [%d] larger than " | ||
253 | "the maximum key size [%d]\n", | ||
254 | session_key->decrypted_key_size, | ||
255 | ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); | ||
256 | rc = -EIO; | ||
257 | goto out; | ||
258 | } | ||
259 | memcpy(session_key->decrypted_key, &data[i], | ||
260 | session_key->decrypted_key_size); | ||
261 | i += session_key->decrypted_key_size; | ||
262 | expected_checksum += (unsigned char)(data[i++]) << 8; | ||
263 | expected_checksum += (unsigned char)(data[i++]); | ||
264 | for (i = 0; i < session_key->decrypted_key_size; i++) | ||
265 | checksum += session_key->decrypted_key[i]; | ||
266 | if (expected_checksum != checksum) { | ||
267 | ecryptfs_printk(KERN_ERR, "Invalid checksum for file " | ||
268 | "encryption key; expected [%x]; calculated " | ||
269 | "[%x]\n", expected_checksum, checksum); | ||
270 | rc = -EIO; | ||
271 | } | ||
272 | out: | ||
273 | return rc; | ||
274 | } | ||
275 | |||
276 | |||
277 | static int | ||
278 | write_tag_66_packet(char *signature, size_t cipher_code, | ||
279 | struct ecryptfs_crypt_stat *crypt_stat, char **packet, | ||
280 | size_t *packet_len) | ||
281 | { | ||
282 | size_t i = 0; | ||
283 | size_t j; | ||
284 | size_t data_len; | ||
285 | size_t checksum = 0; | ||
286 | size_t packet_size_len; | ||
287 | char *message; | ||
288 | int rc; | ||
289 | |||
290 | /* | ||
291 | * ***** TAG 66 Packet Format ***** | ||
292 | * | Content Type | 1 byte | | ||
293 | * | Key Identifier Size | 1 or 2 bytes | | ||
294 | * | Key Identifier | arbitrary | | ||
295 | * | File Encryption Key Size | 1 or 2 bytes | | ||
296 | * | File Encryption Key | arbitrary | | ||
297 | */ | ||
298 | data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size); | ||
299 | *packet = kmalloc(data_len, GFP_KERNEL); | ||
300 | message = *packet; | ||
301 | if (!message) { | ||
302 | ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); | ||
303 | rc = -ENOMEM; | ||
304 | goto out; | ||
305 | } | ||
306 | message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE; | ||
307 | rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX, | ||
308 | &packet_size_len); | ||
309 | if (rc) { | ||
310 | ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet " | ||
311 | "header; cannot generate packet length\n"); | ||
312 | goto out; | ||
313 | } | ||
314 | i += packet_size_len; | ||
315 | memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX); | ||
316 | i += ECRYPTFS_SIG_SIZE_HEX; | ||
317 | /* The encrypted key includes 1 byte cipher code and 2 byte checksum */ | ||
318 | rc = write_packet_length(&message[i], crypt_stat->key_size + 3, | ||
319 | &packet_size_len); | ||
320 | if (rc) { | ||
321 | ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet " | ||
322 | "header; cannot generate packet length\n"); | ||
323 | goto out; | ||
324 | } | ||
325 | i += packet_size_len; | ||
326 | message[i++] = cipher_code; | ||
327 | memcpy(&message[i], crypt_stat->key, crypt_stat->key_size); | ||
328 | i += crypt_stat->key_size; | ||
329 | for (j = 0; j < crypt_stat->key_size; j++) | ||
330 | checksum += crypt_stat->key[j]; | ||
331 | message[i++] = (checksum / 256) % 256; | ||
332 | message[i++] = (checksum % 256); | ||
333 | *packet_len = i; | ||
334 | out: | ||
335 | return rc; | ||
336 | } | ||
337 | |||
338 | static int | ||
339 | parse_tag_67_packet(struct ecryptfs_key_record *key_rec, | ||
340 | struct ecryptfs_message *msg) | ||
341 | { | ||
342 | size_t i = 0; | ||
343 | char *data; | ||
344 | size_t data_len; | ||
345 | size_t message_len; | ||
346 | int rc; | ||
347 | |||
348 | /* | ||
349 | * ***** TAG 65 Packet Format ***** | ||
350 | * | Content Type | 1 byte | | ||
351 | * | Status Indicator | 1 byte | | ||
352 | * | Encrypted File Encryption Key Size | 1 or 2 bytes | | ||
353 | * | Encrypted File Encryption Key | arbitrary | | ||
354 | */ | ||
355 | message_len = msg->data_len; | ||
356 | data = msg->data; | ||
357 | /* verify that everything through the encrypted FEK size is present */ | ||
358 | if (message_len < 4) { | ||
359 | rc = -EIO; | ||
360 | goto out; | ||
361 | } | ||
362 | if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) { | ||
363 | ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_67\n"); | ||
364 | rc = -EIO; | ||
365 | goto out; | ||
366 | } | ||
367 | if (data[i++]) { | ||
368 | ecryptfs_printk(KERN_ERR, "Status indicator has non zero value" | ||
369 | " [%d]\n", data[i-1]); | ||
370 | rc = -EIO; | ||
371 | goto out; | ||
372 | } | ||
373 | rc = parse_packet_length(&data[i], &key_rec->enc_key_size, &data_len); | ||
374 | if (rc) { | ||
375 | ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " | ||
376 | "rc = [%d]\n", rc); | ||
377 | goto out; | ||
378 | } | ||
379 | i += data_len; | ||
380 | if (message_len < (i + key_rec->enc_key_size)) { | ||
381 | ecryptfs_printk(KERN_ERR, "message_len [%d]; max len is [%d]\n", | ||
382 | message_len, (i + key_rec->enc_key_size)); | ||
383 | rc = -EIO; | ||
384 | goto out; | ||
385 | } | ||
386 | if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { | ||
387 | ecryptfs_printk(KERN_ERR, "Encrypted key_size [%d] larger than " | ||
388 | "the maximum key size [%d]\n", | ||
389 | key_rec->enc_key_size, | ||
390 | ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); | ||
391 | rc = -EIO; | ||
392 | goto out; | ||
393 | } | ||
394 | memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size); | ||
395 | out: | ||
396 | return rc; | ||
397 | } | ||
398 | |||
399 | /** | ||
400 | * decrypt_pki_encrypted_session_key - Decrypt the session key with | ||
401 | * the given auth_tok. | ||
402 | * | ||
403 | * Returns Zero on success; non-zero error otherwise. | ||
404 | */ | ||
405 | static int decrypt_pki_encrypted_session_key( | ||
406 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, | ||
407 | struct ecryptfs_auth_tok *auth_tok, | ||
408 | struct ecryptfs_crypt_stat *crypt_stat) | ||
409 | { | ||
410 | u16 cipher_code = 0; | ||
411 | struct ecryptfs_msg_ctx *msg_ctx; | ||
412 | struct ecryptfs_message *msg = NULL; | ||
413 | char *netlink_message; | ||
414 | size_t netlink_message_length; | ||
415 | int rc; | ||
416 | |||
417 | rc = write_tag_64_packet(mount_crypt_stat->global_auth_tok_sig, | ||
418 | &(auth_tok->session_key), | ||
419 | &netlink_message, &netlink_message_length); | ||
420 | if (rc) { | ||
421 | ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet"); | ||
422 | goto out; | ||
423 | } | ||
424 | rc = ecryptfs_send_message(ecryptfs_transport, netlink_message, | ||
425 | netlink_message_length, &msg_ctx); | ||
426 | if (rc) { | ||
427 | ecryptfs_printk(KERN_ERR, "Error sending netlink message\n"); | ||
428 | goto out; | ||
429 | } | ||
430 | rc = ecryptfs_wait_for_response(msg_ctx, &msg); | ||
431 | if (rc) { | ||
432 | ecryptfs_printk(KERN_ERR, "Failed to receive tag 65 packet " | ||
433 | "from the user space daemon\n"); | ||
434 | rc = -EIO; | ||
435 | goto out; | ||
436 | } | ||
437 | rc = parse_tag_65_packet(&(auth_tok->session_key), | ||
438 | &cipher_code, msg); | ||
439 | if (rc) { | ||
440 | printk(KERN_ERR "Failed to parse tag 65 packet; rc = [%d]\n", | ||
441 | rc); | ||
442 | goto out; | ||
443 | } | ||
444 | auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY; | ||
445 | memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key, | ||
446 | auth_tok->session_key.decrypted_key_size); | ||
447 | crypt_stat->key_size = auth_tok->session_key.decrypted_key_size; | ||
448 | rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code); | ||
449 | if (rc) { | ||
450 | ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n", | ||
451 | cipher_code) | ||
452 | goto out; | ||
453 | } | ||
454 | crypt_stat->flags |= ECRYPTFS_KEY_VALID; | ||
455 | if (ecryptfs_verbosity > 0) { | ||
456 | ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n"); | ||
457 | ecryptfs_dump_hex(crypt_stat->key, | ||
458 | crypt_stat->key_size); | ||
459 | } | ||
460 | out: | ||
461 | if (msg) | ||
462 | kfree(msg); | ||
463 | return rc; | ||
464 | } | ||
465 | |||
466 | static void wipe_auth_tok_list(struct list_head *auth_tok_list_head) | ||
467 | { | ||
468 | struct list_head *walker; | ||
469 | struct ecryptfs_auth_tok_list_item *auth_tok_list_item; | ||
470 | |||
471 | walker = auth_tok_list_head->next; | ||
472 | while (walker != auth_tok_list_head) { | ||
473 | auth_tok_list_item = | ||
474 | list_entry(walker, struct ecryptfs_auth_tok_list_item, | ||
475 | list); | ||
476 | walker = auth_tok_list_item->list.next; | ||
477 | memset(auth_tok_list_item, 0, | ||
478 | sizeof(struct ecryptfs_auth_tok_list_item)); | ||
479 | kmem_cache_free(ecryptfs_auth_tok_list_item_cache, | ||
480 | auth_tok_list_item); | ||
481 | } | ||
482 | auth_tok_list_head->next = NULL; | ||
483 | } | ||
484 | |||
485 | struct kmem_cache *ecryptfs_auth_tok_list_item_cache; | ||
486 | |||
487 | |||
488 | /** | ||
489 | * parse_tag_1_packet | ||
490 | * @crypt_stat: The cryptographic context to modify based on packet | ||
491 | * contents. | ||
492 | * @data: The raw bytes of the packet. | ||
493 | * @auth_tok_list: eCryptfs parses packets into authentication tokens; | ||
494 | * a new authentication token will be placed at the end | ||
495 | * of this list for this packet. | ||
496 | * @new_auth_tok: Pointer to a pointer to memory that this function | ||
497 | * allocates; sets the memory address of the pointer to | ||
498 | * NULL on error. This object is added to the | ||
499 | * auth_tok_list. | ||
500 | * @packet_size: This function writes the size of the parsed packet | ||
501 | * into this memory location; zero on error. | ||
502 | * | ||
503 | * Returns zero on success; non-zero on error. | ||
504 | */ | ||
505 | static int | ||
506 | parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat, | ||
507 | unsigned char *data, struct list_head *auth_tok_list, | ||
508 | struct ecryptfs_auth_tok **new_auth_tok, | ||
509 | size_t *packet_size, size_t max_packet_size) | ||
510 | { | ||
511 | size_t body_size; | ||
512 | struct ecryptfs_auth_tok_list_item *auth_tok_list_item; | ||
513 | size_t length_size; | ||
514 | int rc = 0; | ||
515 | |||
516 | (*packet_size) = 0; | ||
517 | (*new_auth_tok) = NULL; | ||
518 | |||
519 | /* we check that: | ||
520 | * one byte for the Tag 1 ID flag | ||
521 | * two bytes for the body size | ||
522 | * do not exceed the maximum_packet_size | ||
523 | */ | ||
524 | if (unlikely((*packet_size) + 3 > max_packet_size)) { | ||
525 | ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); | ||
526 | rc = -EINVAL; | ||
527 | goto out; | ||
528 | } | ||
529 | /* check for Tag 1 identifier - one byte */ | ||
530 | if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) { | ||
531 | ecryptfs_printk(KERN_ERR, "Enter w/ first byte != 0x%.2x\n", | ||
532 | ECRYPTFS_TAG_1_PACKET_TYPE); | ||
533 | rc = -EINVAL; | ||
534 | goto out; | ||
535 | } | ||
536 | /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or | ||
537 | * at end of function upon failure */ | ||
538 | auth_tok_list_item = | ||
539 | kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache, | ||
540 | GFP_KERNEL); | ||
541 | if (!auth_tok_list_item) { | ||
542 | ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); | ||
543 | rc = -ENOMEM; | ||
544 | goto out; | ||
545 | } | ||
546 | memset(auth_tok_list_item, 0, | ||
547 | sizeof(struct ecryptfs_auth_tok_list_item)); | ||
548 | (*new_auth_tok) = &auth_tok_list_item->auth_tok; | ||
549 | /* check for body size - one to two bytes | ||
550 | * | ||
551 | * ***** TAG 1 Packet Format ***** | ||
552 | * | version number | 1 byte | | ||
553 | * | key ID | 8 bytes | | ||
554 | * | public key algorithm | 1 byte | | ||
555 | * | encrypted session key | arbitrary | | ||
556 | */ | ||
557 | rc = parse_packet_length(&data[(*packet_size)], &body_size, | ||
558 | &length_size); | ||
559 | if (rc) { | ||
560 | ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " | ||
561 | "rc = [%d]\n", rc); | ||
562 | goto out_free; | ||
563 | } | ||
564 | if (unlikely(body_size < (0x02 + ECRYPTFS_SIG_SIZE))) { | ||
565 | ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n", | ||
566 | body_size); | ||
567 | rc = -EINVAL; | ||
568 | goto out_free; | ||
569 | } | ||
570 | (*packet_size) += length_size; | ||
571 | if (unlikely((*packet_size) + body_size > max_packet_size)) { | ||
572 | ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); | ||
573 | rc = -EINVAL; | ||
574 | goto out_free; | ||
575 | } | ||
576 | /* Version 3 (from RFC2440) - one byte */ | ||
577 | if (unlikely(data[(*packet_size)++] != 0x03)) { | ||
578 | ecryptfs_printk(KERN_DEBUG, "Unknown version number " | ||
579 | "[%d]\n", data[(*packet_size) - 1]); | ||
580 | rc = -EINVAL; | ||
581 | goto out_free; | ||
582 | } | ||
583 | /* Read Signature */ | ||
584 | ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature, | ||
585 | &data[(*packet_size)], ECRYPTFS_SIG_SIZE); | ||
586 | *packet_size += ECRYPTFS_SIG_SIZE; | ||
587 | /* This byte is skipped because the kernel does not need to | ||
588 | * know which public key encryption algorithm was used */ | ||
589 | (*packet_size)++; | ||
590 | (*new_auth_tok)->session_key.encrypted_key_size = | ||
591 | body_size - (0x02 + ECRYPTFS_SIG_SIZE); | ||
592 | if ((*new_auth_tok)->session_key.encrypted_key_size | ||
593 | > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { | ||
594 | ecryptfs_printk(KERN_ERR, "Tag 1 packet contains key larger " | ||
595 | "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES"); | ||
596 | rc = -EINVAL; | ||
597 | goto out; | ||
598 | } | ||
599 | ecryptfs_printk(KERN_DEBUG, "Encrypted key size = [%d]\n", | ||
600 | (*new_auth_tok)->session_key.encrypted_key_size); | ||
601 | memcpy((*new_auth_tok)->session_key.encrypted_key, | ||
602 | &data[(*packet_size)], (body_size - 0x02 - ECRYPTFS_SIG_SIZE)); | ||
603 | (*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size; | ||
604 | (*new_auth_tok)->session_key.flags &= | ||
605 | ~ECRYPTFS_CONTAINS_DECRYPTED_KEY; | ||
606 | (*new_auth_tok)->session_key.flags |= | ||
607 | ECRYPTFS_CONTAINS_ENCRYPTED_KEY; | ||
608 | (*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY; | ||
609 | (*new_auth_tok)->flags |= ECRYPTFS_PRIVATE_KEY; | ||
610 | /* TODO: Why are we setting this flag here? Don't we want the | ||
611 | * userspace to decrypt the session key? */ | ||
612 | (*new_auth_tok)->session_key.flags &= | ||
613 | ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); | ||
614 | (*new_auth_tok)->session_key.flags &= | ||
615 | ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); | ||
616 | list_add(&auth_tok_list_item->list, auth_tok_list); | ||
617 | goto out; | ||
618 | out_free: | ||
619 | (*new_auth_tok) = NULL; | ||
620 | memset(auth_tok_list_item, 0, | ||
621 | sizeof(struct ecryptfs_auth_tok_list_item)); | ||
622 | kmem_cache_free(ecryptfs_auth_tok_list_item_cache, | ||
623 | auth_tok_list_item); | ||
624 | out: | ||
625 | if (rc) | ||
626 | (*packet_size) = 0; | ||
627 | return rc; | ||
628 | } | ||
629 | |||
157 | /** | 630 | /** |
158 | * parse_tag_3_packet | 631 | * parse_tag_3_packet |
159 | * @crypt_stat: The cryptographic context to modify based on packet | 632 | * @crypt_stat: The cryptographic context to modify based on packet |
@@ -178,10 +651,10 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, | |||
178 | struct ecryptfs_auth_tok **new_auth_tok, | 651 | struct ecryptfs_auth_tok **new_auth_tok, |
179 | size_t *packet_size, size_t max_packet_size) | 652 | size_t *packet_size, size_t max_packet_size) |
180 | { | 653 | { |
181 | int rc = 0; | ||
182 | size_t body_size; | 654 | size_t body_size; |
183 | struct ecryptfs_auth_tok_list_item *auth_tok_list_item; | 655 | struct ecryptfs_auth_tok_list_item *auth_tok_list_item; |
184 | size_t length_size; | 656 | size_t length_size; |
657 | int rc = 0; | ||
185 | 658 | ||
186 | (*packet_size) = 0; | 659 | (*packet_size) = 0; |
187 | (*new_auth_tok) = NULL; | 660 | (*new_auth_tok) = NULL; |
@@ -207,14 +680,12 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, | |||
207 | /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or | 680 | /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or |
208 | * at end of function upon failure */ | 681 | * at end of function upon failure */ |
209 | auth_tok_list_item = | 682 | auth_tok_list_item = |
210 | kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL); | 683 | kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL); |
211 | if (!auth_tok_list_item) { | 684 | if (!auth_tok_list_item) { |
212 | ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); | 685 | ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); |
213 | rc = -ENOMEM; | 686 | rc = -ENOMEM; |
214 | goto out; | 687 | goto out; |
215 | } | 688 | } |
216 | memset(auth_tok_list_item, 0, | ||
217 | sizeof(struct ecryptfs_auth_tok_list_item)); | ||
218 | (*new_auth_tok) = &auth_tok_list_item->auth_tok; | 689 | (*new_auth_tok) = &auth_tok_list_item->auth_tok; |
219 | 690 | ||
220 | /* check for body size - one to two bytes */ | 691 | /* check for body size - one to two bytes */ |
@@ -321,10 +792,10 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, | |||
321 | (*new_auth_tok)->token_type = ECRYPTFS_PASSWORD; | 792 | (*new_auth_tok)->token_type = ECRYPTFS_PASSWORD; |
322 | /* TODO: Parametarize; we might actually want userspace to | 793 | /* TODO: Parametarize; we might actually want userspace to |
323 | * decrypt the session key. */ | 794 | * decrypt the session key. */ |
324 | ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags, | 795 | (*new_auth_tok)->session_key.flags &= |
325 | ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); | 796 | ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); |
326 | ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags, | 797 | (*new_auth_tok)->session_key.flags &= |
327 | ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); | 798 | ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); |
328 | list_add(&auth_tok_list_item->list, auth_tok_list); | 799 | list_add(&auth_tok_list_item->list, auth_tok_list); |
329 | goto out; | 800 | goto out; |
330 | out_free: | 801 | out_free: |
@@ -360,9 +831,9 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents, | |||
360 | size_t max_contents_bytes, size_t *tag_11_contents_size, | 831 | size_t max_contents_bytes, size_t *tag_11_contents_size, |
361 | size_t *packet_size, size_t max_packet_size) | 832 | size_t *packet_size, size_t max_packet_size) |
362 | { | 833 | { |
363 | int rc = 0; | ||
364 | size_t body_size; | 834 | size_t body_size; |
365 | size_t length_size; | 835 | size_t length_size; |
836 | int rc = 0; | ||
366 | 837 | ||
367 | (*packet_size) = 0; | 838 | (*packet_size) = 0; |
368 | (*tag_11_contents_size) = 0; | 839 | (*tag_11_contents_size) = 0; |
@@ -461,7 +932,6 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | |||
461 | struct ecryptfs_password *password_s_ptr; | 932 | struct ecryptfs_password *password_s_ptr; |
462 | struct scatterlist src_sg[2], dst_sg[2]; | 933 | struct scatterlist src_sg[2], dst_sg[2]; |
463 | struct mutex *tfm_mutex = NULL; | 934 | struct mutex *tfm_mutex = NULL; |
464 | /* TODO: Use virt_to_scatterlist for these */ | ||
465 | char *encrypted_session_key; | 935 | char *encrypted_session_key; |
466 | char *session_key; | 936 | char *session_key; |
467 | struct blkcipher_desc desc = { | 937 | struct blkcipher_desc desc = { |
@@ -470,8 +940,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | |||
470 | int rc = 0; | 940 | int rc = 0; |
471 | 941 | ||
472 | password_s_ptr = &auth_tok->token.password; | 942 | password_s_ptr = &auth_tok->token.password; |
473 | if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags, | 943 | if (password_s_ptr->flags & ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) |
474 | ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)) | ||
475 | ecryptfs_printk(KERN_DEBUG, "Session key encryption key " | 944 | ecryptfs_printk(KERN_DEBUG, "Session key encryption key " |
476 | "set; skipping key generation\n"); | 945 | "set; skipping key generation\n"); |
477 | ecryptfs_printk(KERN_DEBUG, "Session key encryption key (size [%d])" | 946 | ecryptfs_printk(KERN_DEBUG, "Session key encryption key (size [%d])" |
@@ -553,7 +1022,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | |||
553 | auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY; | 1022 | auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY; |
554 | memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key, | 1023 | memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key, |
555 | auth_tok->session_key.decrypted_key_size); | 1024 | auth_tok->session_key.decrypted_key_size); |
556 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID); | 1025 | crypt_stat->flags |= ECRYPTFS_KEY_VALID; |
557 | ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n"); | 1026 | ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n"); |
558 | if (ecryptfs_verbosity > 0) | 1027 | if (ecryptfs_verbosity > 0) |
559 | ecryptfs_dump_hex(crypt_stat->key, | 1028 | ecryptfs_dump_hex(crypt_stat->key, |
@@ -589,7 +1058,6 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, | |||
589 | struct dentry *ecryptfs_dentry) | 1058 | struct dentry *ecryptfs_dentry) |
590 | { | 1059 | { |
591 | size_t i = 0; | 1060 | size_t i = 0; |
592 | int rc = 0; | ||
593 | size_t found_auth_tok = 0; | 1061 | size_t found_auth_tok = 0; |
594 | size_t next_packet_is_auth_tok_packet; | 1062 | size_t next_packet_is_auth_tok_packet; |
595 | char sig[ECRYPTFS_SIG_SIZE_HEX]; | 1063 | char sig[ECRYPTFS_SIG_SIZE_HEX]; |
@@ -605,6 +1073,7 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, | |||
605 | unsigned char sig_tmp_space[ECRYPTFS_SIG_SIZE]; | 1073 | unsigned char sig_tmp_space[ECRYPTFS_SIG_SIZE]; |
606 | size_t tag_11_contents_size; | 1074 | size_t tag_11_contents_size; |
607 | size_t tag_11_packet_size; | 1075 | size_t tag_11_packet_size; |
1076 | int rc = 0; | ||
608 | 1077 | ||
609 | INIT_LIST_HEAD(&auth_tok_list); | 1078 | INIT_LIST_HEAD(&auth_tok_list); |
610 | /* Parse the header to find as many packets as we can, these will be | 1079 | /* Parse the header to find as many packets as we can, these will be |
@@ -656,8 +1125,21 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, | |||
656 | sig_tmp_space, tag_11_contents_size); | 1125 | sig_tmp_space, tag_11_contents_size); |
657 | new_auth_tok->token.password.signature[ | 1126 | new_auth_tok->token.password.signature[ |
658 | ECRYPTFS_PASSWORD_SIG_SIZE] = '\0'; | 1127 | ECRYPTFS_PASSWORD_SIG_SIZE] = '\0'; |
659 | ECRYPTFS_SET_FLAG(crypt_stat->flags, | 1128 | crypt_stat->flags |= ECRYPTFS_ENCRYPTED; |
660 | ECRYPTFS_ENCRYPTED); | 1129 | break; |
1130 | case ECRYPTFS_TAG_1_PACKET_TYPE: | ||
1131 | rc = parse_tag_1_packet(crypt_stat, | ||
1132 | (unsigned char *)&src[i], | ||
1133 | &auth_tok_list, &new_auth_tok, | ||
1134 | &packet_size, max_packet_size); | ||
1135 | if (rc) { | ||
1136 | ecryptfs_printk(KERN_ERR, "Error parsing " | ||
1137 | "tag 1 packet\n"); | ||
1138 | rc = -EIO; | ||
1139 | goto out_wipe_list; | ||
1140 | } | ||
1141 | i += packet_size; | ||
1142 | crypt_stat->flags |= ECRYPTFS_ENCRYPTED; | ||
661 | break; | 1143 | break; |
662 | case ECRYPTFS_TAG_11_PACKET_TYPE: | 1144 | case ECRYPTFS_TAG_11_PACKET_TYPE: |
663 | ecryptfs_printk(KERN_WARNING, "Invalid packet set " | 1145 | ecryptfs_printk(KERN_WARNING, "Invalid packet set " |
@@ -706,31 +1188,46 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, | |||
706 | goto leave_list; | 1188 | goto leave_list; |
707 | /* TODO: Transfer the common salt into the | 1189 | /* TODO: Transfer the common salt into the |
708 | * crypt_stat salt */ | 1190 | * crypt_stat salt */ |
1191 | } else if ((candidate_auth_tok->token_type | ||
1192 | == ECRYPTFS_PRIVATE_KEY) | ||
1193 | && !strncmp(candidate_auth_tok->token.private_key.signature, | ||
1194 | sig, ECRYPTFS_SIG_SIZE_HEX)) { | ||
1195 | found_auth_tok = 1; | ||
1196 | goto leave_list; | ||
709 | } | 1197 | } |
710 | } | 1198 | } |
711 | leave_list: | ||
712 | if (!found_auth_tok) { | 1199 | if (!found_auth_tok) { |
713 | ecryptfs_printk(KERN_ERR, "Could not find authentication " | 1200 | ecryptfs_printk(KERN_ERR, "Could not find authentication " |
714 | "token on temporary list for sig [%.*s]\n", | 1201 | "token on temporary list for sig [%.*s]\n", |
715 | ECRYPTFS_SIG_SIZE_HEX, sig); | 1202 | ECRYPTFS_SIG_SIZE_HEX, sig); |
716 | rc = -EIO; | 1203 | rc = -EIO; |
717 | goto out_wipe_list; | 1204 | goto out_wipe_list; |
718 | } else { | 1205 | } |
1206 | leave_list: | ||
1207 | rc = -ENOTSUPP; | ||
1208 | if (candidate_auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { | ||
1209 | memcpy(&(candidate_auth_tok->token.private_key), | ||
1210 | &(chosen_auth_tok->token.private_key), | ||
1211 | sizeof(struct ecryptfs_private_key)); | ||
1212 | rc = decrypt_pki_encrypted_session_key(mount_crypt_stat, | ||
1213 | candidate_auth_tok, | ||
1214 | crypt_stat); | ||
1215 | } else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) { | ||
719 | memcpy(&(candidate_auth_tok->token.password), | 1216 | memcpy(&(candidate_auth_tok->token.password), |
720 | &(chosen_auth_tok->token.password), | 1217 | &(chosen_auth_tok->token.password), |
721 | sizeof(struct ecryptfs_password)); | 1218 | sizeof(struct ecryptfs_password)); |
722 | rc = decrypt_session_key(candidate_auth_tok, crypt_stat); | 1219 | rc = decrypt_session_key(candidate_auth_tok, crypt_stat); |
723 | if (rc) { | 1220 | } |
724 | ecryptfs_printk(KERN_ERR, "Error decrypting the " | 1221 | if (rc) { |
725 | "session key\n"); | 1222 | ecryptfs_printk(KERN_ERR, "Error decrypting the " |
726 | goto out_wipe_list; | 1223 | "session key; rc = [%d]\n", rc); |
727 | } | 1224 | goto out_wipe_list; |
728 | rc = ecryptfs_compute_root_iv(crypt_stat); | 1225 | } |
729 | if (rc) { | 1226 | rc = ecryptfs_compute_root_iv(crypt_stat); |
730 | ecryptfs_printk(KERN_ERR, "Error computing " | 1227 | if (rc) { |
731 | "the root IV\n"); | 1228 | ecryptfs_printk(KERN_ERR, "Error computing " |
732 | goto out_wipe_list; | 1229 | "the root IV\n"); |
733 | } | 1230 | goto out_wipe_list; |
734 | } | 1231 | } |
735 | rc = ecryptfs_init_crypt_ctx(crypt_stat); | 1232 | rc = ecryptfs_init_crypt_ctx(crypt_stat); |
736 | if (rc) { | 1233 | if (rc) { |
@@ -743,6 +1240,145 @@ out_wipe_list: | |||
743 | out: | 1240 | out: |
744 | return rc; | 1241 | return rc; |
745 | } | 1242 | } |
1243 | static int | ||
1244 | pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok, | ||
1245 | struct ecryptfs_crypt_stat *crypt_stat, | ||
1246 | struct ecryptfs_key_record *key_rec) | ||
1247 | { | ||
1248 | struct ecryptfs_msg_ctx *msg_ctx = NULL; | ||
1249 | char *netlink_payload; | ||
1250 | size_t netlink_payload_length; | ||
1251 | struct ecryptfs_message *msg; | ||
1252 | int rc; | ||
1253 | |||
1254 | rc = write_tag_66_packet(auth_tok->token.private_key.signature, | ||
1255 | ecryptfs_code_for_cipher_string(crypt_stat), | ||
1256 | crypt_stat, &netlink_payload, | ||
1257 | &netlink_payload_length); | ||
1258 | if (rc) { | ||
1259 | ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n"); | ||
1260 | goto out; | ||
1261 | } | ||
1262 | rc = ecryptfs_send_message(ecryptfs_transport, netlink_payload, | ||
1263 | netlink_payload_length, &msg_ctx); | ||
1264 | if (rc) { | ||
1265 | ecryptfs_printk(KERN_ERR, "Error sending netlink message\n"); | ||
1266 | goto out; | ||
1267 | } | ||
1268 | rc = ecryptfs_wait_for_response(msg_ctx, &msg); | ||
1269 | if (rc) { | ||
1270 | ecryptfs_printk(KERN_ERR, "Failed to receive tag 67 packet " | ||
1271 | "from the user space daemon\n"); | ||
1272 | rc = -EIO; | ||
1273 | goto out; | ||
1274 | } | ||
1275 | rc = parse_tag_67_packet(key_rec, msg); | ||
1276 | if (rc) | ||
1277 | ecryptfs_printk(KERN_ERR, "Error parsing tag 67 packet\n"); | ||
1278 | kfree(msg); | ||
1279 | out: | ||
1280 | if (netlink_payload) | ||
1281 | kfree(netlink_payload); | ||
1282 | return rc; | ||
1283 | } | ||
1284 | /** | ||
1285 | * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet | ||
1286 | * @dest: Buffer into which to write the packet | ||
1287 | * @max: Maximum number of bytes that can be writtn | ||
1288 | * @packet_size: This function will write the number of bytes that end | ||
1289 | * up constituting the packet; set to zero on error | ||
1290 | * | ||
1291 | * Returns zero on success; non-zero on error. | ||
1292 | */ | ||
1293 | static int | ||
1294 | write_tag_1_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, | ||
1295 | struct ecryptfs_crypt_stat *crypt_stat, | ||
1296 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, | ||
1297 | struct ecryptfs_key_record *key_rec, size_t *packet_size) | ||
1298 | { | ||
1299 | size_t i; | ||
1300 | size_t encrypted_session_key_valid = 0; | ||
1301 | size_t key_rec_size; | ||
1302 | size_t packet_size_length; | ||
1303 | int rc = 0; | ||
1304 | |||
1305 | (*packet_size) = 0; | ||
1306 | ecryptfs_from_hex(key_rec->sig, auth_tok->token.private_key.signature, | ||
1307 | ECRYPTFS_SIG_SIZE); | ||
1308 | encrypted_session_key_valid = 0; | ||
1309 | for (i = 0; i < crypt_stat->key_size; i++) | ||
1310 | encrypted_session_key_valid |= | ||
1311 | auth_tok->session_key.encrypted_key[i]; | ||
1312 | if (encrypted_session_key_valid) { | ||
1313 | memcpy(key_rec->enc_key, | ||
1314 | auth_tok->session_key.encrypted_key, | ||
1315 | auth_tok->session_key.encrypted_key_size); | ||
1316 | goto encrypted_session_key_set; | ||
1317 | } | ||
1318 | if (auth_tok->session_key.encrypted_key_size == 0) | ||
1319 | auth_tok->session_key.encrypted_key_size = | ||
1320 | auth_tok->token.private_key.key_size; | ||
1321 | rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec); | ||
1322 | if (rc) { | ||
1323 | ecryptfs_printk(KERN_ERR, "Failed to encrypt session key " | ||
1324 | "via a pki"); | ||
1325 | goto out; | ||
1326 | } | ||
1327 | if (ecryptfs_verbosity > 0) { | ||
1328 | ecryptfs_printk(KERN_DEBUG, "Encrypted key:\n"); | ||
1329 | ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size); | ||
1330 | } | ||
1331 | encrypted_session_key_set: | ||
1332 | /* Now we have a valid key_rec. Append it to the | ||
1333 | * key_rec set. */ | ||
1334 | key_rec_size = (sizeof(struct ecryptfs_key_record) | ||
1335 | - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES | ||
1336 | + (key_rec->enc_key_size)); | ||
1337 | /* TODO: Include a packet size limit as a parameter to this | ||
1338 | * function once we have multi-packet headers (for versions | ||
1339 | * later than 0.1 */ | ||
1340 | if (key_rec_size >= ECRYPTFS_MAX_KEYSET_SIZE) { | ||
1341 | ecryptfs_printk(KERN_ERR, "Keyset too large\n"); | ||
1342 | rc = -EINVAL; | ||
1343 | goto out; | ||
1344 | } | ||
1345 | /* ***** TAG 1 Packet Format ***** | ||
1346 | * | version number | 1 byte | | ||
1347 | * | key ID | 8 bytes | | ||
1348 | * | public key algorithm | 1 byte | | ||
1349 | * | encrypted session key | arbitrary | | ||
1350 | */ | ||
1351 | if ((0x02 + ECRYPTFS_SIG_SIZE + key_rec->enc_key_size) >= max) { | ||
1352 | ecryptfs_printk(KERN_ERR, | ||
1353 | "Authentication token is too large\n"); | ||
1354 | rc = -EINVAL; | ||
1355 | goto out; | ||
1356 | } | ||
1357 | dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE; | ||
1358 | /* This format is inspired by OpenPGP; see RFC 2440 | ||
1359 | * packet tag 1 */ | ||
1360 | rc = write_packet_length(&dest[(*packet_size)], | ||
1361 | (0x02 + ECRYPTFS_SIG_SIZE + | ||
1362 | key_rec->enc_key_size), | ||
1363 | &packet_size_length); | ||
1364 | if (rc) { | ||
1365 | ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet " | ||
1366 | "header; cannot generate packet length\n"); | ||
1367 | goto out; | ||
1368 | } | ||
1369 | (*packet_size) += packet_size_length; | ||
1370 | dest[(*packet_size)++] = 0x03; /* version 3 */ | ||
1371 | memcpy(&dest[(*packet_size)], key_rec->sig, ECRYPTFS_SIG_SIZE); | ||
1372 | (*packet_size) += ECRYPTFS_SIG_SIZE; | ||
1373 | dest[(*packet_size)++] = RFC2440_CIPHER_RSA; | ||
1374 | memcpy(&dest[(*packet_size)], key_rec->enc_key, | ||
1375 | key_rec->enc_key_size); | ||
1376 | (*packet_size) += key_rec->enc_key_size; | ||
1377 | out: | ||
1378 | if (rc) | ||
1379 | (*packet_size) = 0; | ||
1380 | return rc; | ||
1381 | } | ||
746 | 1382 | ||
747 | /** | 1383 | /** |
748 | * write_tag_11_packet | 1384 | * write_tag_11_packet |
@@ -758,8 +1394,8 @@ static int | |||
758 | write_tag_11_packet(char *dest, int max, char *contents, size_t contents_length, | 1394 | write_tag_11_packet(char *dest, int max, char *contents, size_t contents_length, |
759 | size_t *packet_length) | 1395 | size_t *packet_length) |
760 | { | 1396 | { |
761 | int rc = 0; | ||
762 | size_t packet_size_length; | 1397 | size_t packet_size_length; |
1398 | int rc = 0; | ||
763 | 1399 | ||
764 | (*packet_length) = 0; | 1400 | (*packet_length) = 0; |
765 | if ((13 + contents_length) > max) { | 1401 | if ((13 + contents_length) > max) { |
@@ -817,7 +1453,6 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, | |||
817 | struct ecryptfs_key_record *key_rec, size_t *packet_size) | 1453 | struct ecryptfs_key_record *key_rec, size_t *packet_size) |
818 | { | 1454 | { |
819 | size_t i; | 1455 | size_t i; |
820 | size_t signature_is_valid = 0; | ||
821 | size_t encrypted_session_key_valid = 0; | 1456 | size_t encrypted_session_key_valid = 0; |
822 | char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; | 1457 | char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; |
823 | struct scatterlist dest_sg[2]; | 1458 | struct scatterlist dest_sg[2]; |
@@ -833,19 +1468,14 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, | |||
833 | int rc = 0; | 1468 | int rc = 0; |
834 | 1469 | ||
835 | (*packet_size) = 0; | 1470 | (*packet_size) = 0; |
836 | /* Check for a valid signature on the auth_tok */ | 1471 | ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature, |
837 | for (i = 0; i < ECRYPTFS_SIG_SIZE_HEX; i++) | ||
838 | signature_is_valid |= auth_tok->token.password.signature[i]; | ||
839 | if (!signature_is_valid) | ||
840 | BUG(); | ||
841 | ecryptfs_from_hex((*key_rec).sig, auth_tok->token.password.signature, | ||
842 | ECRYPTFS_SIG_SIZE); | 1472 | ECRYPTFS_SIG_SIZE); |
843 | encrypted_session_key_valid = 0; | 1473 | encrypted_session_key_valid = 0; |
844 | for (i = 0; i < crypt_stat->key_size; i++) | 1474 | for (i = 0; i < crypt_stat->key_size; i++) |
845 | encrypted_session_key_valid |= | 1475 | encrypted_session_key_valid |= |
846 | auth_tok->session_key.encrypted_key[i]; | 1476 | auth_tok->session_key.encrypted_key[i]; |
847 | if (encrypted_session_key_valid) { | 1477 | if (encrypted_session_key_valid) { |
848 | memcpy((*key_rec).enc_key, | 1478 | memcpy(key_rec->enc_key, |
849 | auth_tok->session_key.encrypted_key, | 1479 | auth_tok->session_key.encrypted_key, |
850 | auth_tok->session_key.encrypted_key_size); | 1480 | auth_tok->session_key.encrypted_key_size); |
851 | goto encrypted_session_key_set; | 1481 | goto encrypted_session_key_set; |
@@ -858,10 +1488,10 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, | |||
858 | memset((crypt_stat->key + 24), 0, 8); | 1488 | memset((crypt_stat->key + 24), 0, 8); |
859 | auth_tok->session_key.encrypted_key_size = 32; | 1489 | auth_tok->session_key.encrypted_key_size = 32; |
860 | } | 1490 | } |
861 | (*key_rec).enc_key_size = | 1491 | key_rec->enc_key_size = |
862 | auth_tok->session_key.encrypted_key_size; | 1492 | auth_tok->session_key.encrypted_key_size; |
863 | if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags, | 1493 | if (auth_tok->token.password.flags & |
864 | ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)) { | 1494 | ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) { |
865 | ecryptfs_printk(KERN_DEBUG, "Using previously generated " | 1495 | ecryptfs_printk(KERN_DEBUG, "Using previously generated " |
866 | "session key encryption key of size [%d]\n", | 1496 | "session key encryption key of size [%d]\n", |
867 | auth_tok->token.password. | 1497 | auth_tok->token.password. |
@@ -879,15 +1509,15 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, | |||
879 | ecryptfs_dump_hex(session_key_encryption_key, 16); | 1509 | ecryptfs_dump_hex(session_key_encryption_key, 16); |
880 | } | 1510 | } |
881 | rc = virt_to_scatterlist(crypt_stat->key, | 1511 | rc = virt_to_scatterlist(crypt_stat->key, |
882 | (*key_rec).enc_key_size, src_sg, 2); | 1512 | key_rec->enc_key_size, src_sg, 2); |
883 | if (!rc) { | 1513 | if (!rc) { |
884 | ecryptfs_printk(KERN_ERR, "Error generating scatterlist " | 1514 | ecryptfs_printk(KERN_ERR, "Error generating scatterlist " |
885 | "for crypt_stat session key\n"); | 1515 | "for crypt_stat session key\n"); |
886 | rc = -ENOMEM; | 1516 | rc = -ENOMEM; |
887 | goto out; | 1517 | goto out; |
888 | } | 1518 | } |
889 | rc = virt_to_scatterlist((*key_rec).enc_key, | 1519 | rc = virt_to_scatterlist(key_rec->enc_key, |
890 | (*key_rec).enc_key_size, dest_sg, 2); | 1520 | key_rec->enc_key_size, dest_sg, 2); |
891 | if (!rc) { | 1521 | if (!rc) { |
892 | ecryptfs_printk(KERN_ERR, "Error generating scatterlist " | 1522 | ecryptfs_printk(KERN_ERR, "Error generating scatterlist " |
893 | "for crypt_stat encrypted session key\n"); | 1523 | "for crypt_stat encrypted session key\n"); |
@@ -943,14 +1573,14 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, | |||
943 | mutex_unlock(tfm_mutex); | 1573 | mutex_unlock(tfm_mutex); |
944 | ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); | 1574 | ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); |
945 | if (ecryptfs_verbosity > 0) | 1575 | if (ecryptfs_verbosity > 0) |
946 | ecryptfs_dump_hex((*key_rec).enc_key, | 1576 | ecryptfs_dump_hex(key_rec->enc_key, |
947 | (*key_rec).enc_key_size); | 1577 | key_rec->enc_key_size); |
948 | encrypted_session_key_set: | 1578 | encrypted_session_key_set: |
949 | /* Now we have a valid key_rec. Append it to the | 1579 | /* Now we have a valid key_rec. Append it to the |
950 | * key_rec set. */ | 1580 | * key_rec set. */ |
951 | key_rec_size = (sizeof(struct ecryptfs_key_record) | 1581 | key_rec_size = (sizeof(struct ecryptfs_key_record) |
952 | - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES | 1582 | - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES |
953 | + ((*key_rec).enc_key_size)); | 1583 | + (key_rec->enc_key_size)); |
954 | /* TODO: Include a packet size limit as a parameter to this | 1584 | /* TODO: Include a packet size limit as a parameter to this |
955 | * function once we have multi-packet headers (for versions | 1585 | * function once we have multi-packet headers (for versions |
956 | * later than 0.1 */ | 1586 | * later than 0.1 */ |
@@ -962,7 +1592,7 @@ encrypted_session_key_set: | |||
962 | /* TODO: Packet size limit */ | 1592 | /* TODO: Packet size limit */ |
963 | /* We have 5 bytes of surrounding packet data */ | 1593 | /* We have 5 bytes of surrounding packet data */ |
964 | if ((0x05 + ECRYPTFS_SALT_SIZE | 1594 | if ((0x05 + ECRYPTFS_SALT_SIZE |
965 | + (*key_rec).enc_key_size) >= max) { | 1595 | + key_rec->enc_key_size) >= max) { |
966 | ecryptfs_printk(KERN_ERR, "Authentication token is too " | 1596 | ecryptfs_printk(KERN_ERR, "Authentication token is too " |
967 | "large\n"); | 1597 | "large\n"); |
968 | rc = -EINVAL; | 1598 | rc = -EINVAL; |
@@ -974,7 +1604,7 @@ encrypted_session_key_set: | |||
974 | /* ver+cipher+s2k+hash+salt+iter+enc_key */ | 1604 | /* ver+cipher+s2k+hash+salt+iter+enc_key */ |
975 | rc = write_packet_length(&dest[(*packet_size)], | 1605 | rc = write_packet_length(&dest[(*packet_size)], |
976 | (0x05 + ECRYPTFS_SALT_SIZE | 1606 | (0x05 + ECRYPTFS_SALT_SIZE |
977 | + (*key_rec).enc_key_size), | 1607 | + key_rec->enc_key_size), |
978 | &packet_size_length); | 1608 | &packet_size_length); |
979 | if (rc) { | 1609 | if (rc) { |
980 | ecryptfs_printk(KERN_ERR, "Error generating tag 3 packet " | 1610 | ecryptfs_printk(KERN_ERR, "Error generating tag 3 packet " |
@@ -997,9 +1627,9 @@ encrypted_session_key_set: | |||
997 | ECRYPTFS_SALT_SIZE); | 1627 | ECRYPTFS_SALT_SIZE); |
998 | (*packet_size) += ECRYPTFS_SALT_SIZE; /* salt */ | 1628 | (*packet_size) += ECRYPTFS_SALT_SIZE; /* salt */ |
999 | dest[(*packet_size)++] = 0x60; /* hash iterations (65536) */ | 1629 | dest[(*packet_size)++] = 0x60; /* hash iterations (65536) */ |
1000 | memcpy(&dest[(*packet_size)], (*key_rec).enc_key, | 1630 | memcpy(&dest[(*packet_size)], key_rec->enc_key, |
1001 | (*key_rec).enc_key_size); | 1631 | key_rec->enc_key_size); |
1002 | (*packet_size) += (*key_rec).enc_key_size; | 1632 | (*packet_size) += key_rec->enc_key_size; |
1003 | out: | 1633 | out: |
1004 | if (desc.tfm && !tfm_mutex) | 1634 | if (desc.tfm && !tfm_mutex) |
1005 | crypto_free_blkcipher(desc.tfm); | 1635 | crypto_free_blkcipher(desc.tfm); |
@@ -1008,6 +1638,8 @@ out: | |||
1008 | return rc; | 1638 | return rc; |
1009 | } | 1639 | } |
1010 | 1640 | ||
1641 | struct kmem_cache *ecryptfs_key_record_cache; | ||
1642 | |||
1011 | /** | 1643 | /** |
1012 | * ecryptfs_generate_key_packet_set | 1644 | * ecryptfs_generate_key_packet_set |
1013 | * @dest: Virtual address from which to write the key record set | 1645 | * @dest: Virtual address from which to write the key record set |
@@ -1029,52 +1661,60 @@ ecryptfs_generate_key_packet_set(char *dest_base, | |||
1029 | struct dentry *ecryptfs_dentry, size_t *len, | 1661 | struct dentry *ecryptfs_dentry, size_t *len, |
1030 | size_t max) | 1662 | size_t max) |
1031 | { | 1663 | { |
1032 | int rc = 0; | ||
1033 | struct ecryptfs_auth_tok *auth_tok; | 1664 | struct ecryptfs_auth_tok *auth_tok; |
1034 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = | 1665 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = |
1035 | &ecryptfs_superblock_to_private( | 1666 | &ecryptfs_superblock_to_private( |
1036 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | 1667 | ecryptfs_dentry->d_sb)->mount_crypt_stat; |
1037 | size_t written; | 1668 | size_t written; |
1038 | struct ecryptfs_key_record key_rec; | 1669 | struct ecryptfs_key_record *key_rec; |
1670 | int rc = 0; | ||
1039 | 1671 | ||
1040 | (*len) = 0; | 1672 | (*len) = 0; |
1673 | key_rec = kmem_cache_alloc(ecryptfs_key_record_cache, GFP_KERNEL); | ||
1674 | if (!key_rec) { | ||
1675 | rc = -ENOMEM; | ||
1676 | goto out; | ||
1677 | } | ||
1041 | if (mount_crypt_stat->global_auth_tok) { | 1678 | if (mount_crypt_stat->global_auth_tok) { |
1042 | auth_tok = mount_crypt_stat->global_auth_tok; | 1679 | auth_tok = mount_crypt_stat->global_auth_tok; |
1043 | if (auth_tok->token_type == ECRYPTFS_PASSWORD) { | 1680 | if (auth_tok->token_type == ECRYPTFS_PASSWORD) { |
1044 | rc = write_tag_3_packet((dest_base + (*len)), | 1681 | rc = write_tag_3_packet((dest_base + (*len)), |
1045 | max, auth_tok, | 1682 | max, auth_tok, |
1046 | crypt_stat, &key_rec, | 1683 | crypt_stat, key_rec, |
1047 | &written); | 1684 | &written); |
1048 | if (rc) { | 1685 | if (rc) { |
1049 | ecryptfs_printk(KERN_WARNING, "Error " | 1686 | ecryptfs_printk(KERN_WARNING, "Error " |
1050 | "writing tag 3 packet\n"); | 1687 | "writing tag 3 packet\n"); |
1051 | goto out; | 1688 | goto out_free; |
1052 | } | 1689 | } |
1053 | (*len) += written; | 1690 | (*len) += written; |
1054 | /* Write auth tok signature packet */ | 1691 | /* Write auth tok signature packet */ |
1055 | rc = write_tag_11_packet( | 1692 | rc = write_tag_11_packet( |
1056 | (dest_base + (*len)), | 1693 | (dest_base + (*len)), |
1057 | (max - (*len)), | 1694 | (max - (*len)), |
1058 | key_rec.sig, ECRYPTFS_SIG_SIZE, &written); | 1695 | key_rec->sig, ECRYPTFS_SIG_SIZE, &written); |
1059 | if (rc) { | 1696 | if (rc) { |
1060 | ecryptfs_printk(KERN_ERR, "Error writing " | 1697 | ecryptfs_printk(KERN_ERR, "Error writing " |
1061 | "auth tok signature packet\n"); | 1698 | "auth tok signature packet\n"); |
1062 | goto out; | 1699 | goto out_free; |
1700 | } | ||
1701 | (*len) += written; | ||
1702 | } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { | ||
1703 | rc = write_tag_1_packet(dest_base + (*len), | ||
1704 | max, auth_tok, | ||
1705 | crypt_stat,mount_crypt_stat, | ||
1706 | key_rec, &written); | ||
1707 | if (rc) { | ||
1708 | ecryptfs_printk(KERN_WARNING, "Error " | ||
1709 | "writing tag 1 packet\n"); | ||
1710 | goto out_free; | ||
1063 | } | 1711 | } |
1064 | (*len) += written; | 1712 | (*len) += written; |
1065 | } else { | 1713 | } else { |
1066 | ecryptfs_printk(KERN_WARNING, "Unsupported " | 1714 | ecryptfs_printk(KERN_WARNING, "Unsupported " |
1067 | "authentication token type\n"); | 1715 | "authentication token type\n"); |
1068 | rc = -EINVAL; | 1716 | rc = -EINVAL; |
1069 | goto out; | 1717 | goto out_free; |
1070 | } | ||
1071 | if (rc) { | ||
1072 | ecryptfs_printk(KERN_WARNING, "Error writing " | ||
1073 | "authentication token packet with sig " | ||
1074 | "= [%s]\n", | ||
1075 | mount_crypt_stat->global_auth_tok_sig); | ||
1076 | rc = -EIO; | ||
1077 | goto out; | ||
1078 | } | 1718 | } |
1079 | } else | 1719 | } else |
1080 | BUG(); | 1720 | BUG(); |
@@ -1084,6 +1724,9 @@ ecryptfs_generate_key_packet_set(char *dest_base, | |||
1084 | ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n"); | 1724 | ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n"); |
1085 | rc = -EIO; | 1725 | rc = -EIO; |
1086 | } | 1726 | } |
1727 | |||
1728 | out_free: | ||
1729 | kmem_cache_free(ecryptfs_key_record_cache, key_rec); | ||
1087 | out: | 1730 | out: |
1088 | if (rc) | 1731 | if (rc) |
1089 | (*len) = 0; | 1732 | (*len) = 0; |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index d0541ae8faba..80044d196fe0 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -3,9 +3,10 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-2003 Erez Zadok | 4 | * Copyright (C) 1997-2003 Erez Zadok |
5 | * Copyright (C) 2001-2003 Stony Brook University | 5 | * Copyright (C) 2001-2003 Stony Brook University |
6 | * Copyright (C) 2004-2006 International Business Machines Corp. | 6 | * Copyright (C) 2004-2007 International Business Machines Corp. |
7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
8 | * Michael C. Thompson <mcthomps@us.ibm.com> | 8 | * Michael C. Thompson <mcthomps@us.ibm.com> |
9 | * Tyler Hicks <tyhicks@ou.edu> | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License as | 12 | * modify it under the terms of the GNU General Public License as |
@@ -48,6 +49,43 @@ MODULE_PARM_DESC(ecryptfs_verbosity, | |||
48 | "Initial verbosity level (0 or 1; defaults to " | 49 | "Initial verbosity level (0 or 1; defaults to " |
49 | "0, which is Quiet)"); | 50 | "0, which is Quiet)"); |
50 | 51 | ||
52 | /** | ||
53 | * Module parameter that defines the number of netlink message buffer | ||
54 | * elements | ||
55 | */ | ||
56 | unsigned int ecryptfs_message_buf_len = ECRYPTFS_DEFAULT_MSG_CTX_ELEMS; | ||
57 | |||
58 | module_param(ecryptfs_message_buf_len, uint, 0); | ||
59 | MODULE_PARM_DESC(ecryptfs_message_buf_len, | ||
60 | "Number of message buffer elements"); | ||
61 | |||
62 | /** | ||
63 | * Module parameter that defines the maximum guaranteed amount of time to wait | ||
64 | * for a response through netlink. The actual sleep time will be, more than | ||
65 | * likely, a small amount greater than this specified value, but only less if | ||
66 | * the netlink message successfully arrives. | ||
67 | */ | ||
68 | signed long ecryptfs_message_wait_timeout = ECRYPTFS_MAX_MSG_CTX_TTL / HZ; | ||
69 | |||
70 | module_param(ecryptfs_message_wait_timeout, long, 0); | ||
71 | MODULE_PARM_DESC(ecryptfs_message_wait_timeout, | ||
72 | "Maximum number of seconds that an operation will " | ||
73 | "sleep while waiting for a message response from " | ||
74 | "userspace"); | ||
75 | |||
76 | /** | ||
77 | * Module parameter that is an estimate of the maximum number of users | ||
78 | * that will be concurrently using eCryptfs. Set this to the right | ||
79 | * value to balance performance and memory use. | ||
80 | */ | ||
81 | unsigned int ecryptfs_number_of_users = ECRYPTFS_DEFAULT_NUM_USERS; | ||
82 | |||
83 | module_param(ecryptfs_number_of_users, uint, 0); | ||
84 | MODULE_PARM_DESC(ecryptfs_number_of_users, "An estimate of the number of " | ||
85 | "concurrent users of eCryptfs"); | ||
86 | |||
87 | unsigned int ecryptfs_transport = ECRYPTFS_DEFAULT_TRANSPORT; | ||
88 | |||
51 | void __ecryptfs_printk(const char *fmt, ...) | 89 | void __ecryptfs_printk(const char *fmt, ...) |
52 | { | 90 | { |
53 | va_list args; | 91 | va_list args; |
@@ -124,7 +162,8 @@ out: | |||
124 | enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug, | 162 | enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug, |
125 | ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher, | 163 | ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher, |
126 | ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes, | 164 | ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes, |
127 | ecryptfs_opt_passthrough, ecryptfs_opt_err }; | 165 | ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata, |
166 | ecryptfs_opt_encrypted_view, ecryptfs_opt_err }; | ||
128 | 167 | ||
129 | static match_table_t tokens = { | 168 | static match_table_t tokens = { |
130 | {ecryptfs_opt_sig, "sig=%s"}, | 169 | {ecryptfs_opt_sig, "sig=%s"}, |
@@ -135,6 +174,8 @@ static match_table_t tokens = { | |||
135 | {ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"}, | 174 | {ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"}, |
136 | {ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"}, | 175 | {ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"}, |
137 | {ecryptfs_opt_passthrough, "ecryptfs_passthrough"}, | 176 | {ecryptfs_opt_passthrough, "ecryptfs_passthrough"}, |
177 | {ecryptfs_opt_xattr_metadata, "ecryptfs_xattr_metadata"}, | ||
178 | {ecryptfs_opt_encrypted_view, "ecryptfs_encrypted_view"}, | ||
138 | {ecryptfs_opt_err, NULL} | 179 | {ecryptfs_opt_err, NULL} |
139 | }; | 180 | }; |
140 | 181 | ||
@@ -275,6 +316,16 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) | |||
275 | mount_crypt_stat->flags |= | 316 | mount_crypt_stat->flags |= |
276 | ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED; | 317 | ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED; |
277 | break; | 318 | break; |
319 | case ecryptfs_opt_xattr_metadata: | ||
320 | mount_crypt_stat->flags |= | ||
321 | ECRYPTFS_XATTR_METADATA_ENABLED; | ||
322 | break; | ||
323 | case ecryptfs_opt_encrypted_view: | ||
324 | mount_crypt_stat->flags |= | ||
325 | ECRYPTFS_XATTR_METADATA_ENABLED; | ||
326 | mount_crypt_stat->flags |= | ||
327 | ECRYPTFS_ENCRYPTED_VIEW_ENABLED; | ||
328 | break; | ||
278 | case ecryptfs_opt_err: | 329 | case ecryptfs_opt_err: |
279 | default: | 330 | default: |
280 | ecryptfs_printk(KERN_WARNING, | 331 | ecryptfs_printk(KERN_WARNING, |
@@ -347,9 +398,10 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) | |||
347 | rc = -EINVAL; | 398 | rc = -EINVAL; |
348 | goto out; | 399 | goto out; |
349 | } | 400 | } |
350 | if (auth_tok->token_type != ECRYPTFS_PASSWORD) { | 401 | if (auth_tok->token_type != ECRYPTFS_PASSWORD |
402 | && auth_tok->token_type != ECRYPTFS_PRIVATE_KEY) { | ||
351 | ecryptfs_printk(KERN_ERR, "Invalid auth_tok structure " | 403 | ecryptfs_printk(KERN_ERR, "Invalid auth_tok structure " |
352 | "returned from key\n"); | 404 | "returned from key query\n"); |
353 | rc = -EINVAL; | 405 | rc = -EINVAL; |
354 | goto out; | 406 | goto out; |
355 | } | 407 | } |
@@ -378,15 +430,13 @@ ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
378 | 430 | ||
379 | /* Released in ecryptfs_put_super() */ | 431 | /* Released in ecryptfs_put_super() */ |
380 | ecryptfs_set_superblock_private(sb, | 432 | ecryptfs_set_superblock_private(sb, |
381 | kmem_cache_alloc(ecryptfs_sb_info_cache, | 433 | kmem_cache_zalloc(ecryptfs_sb_info_cache, |
382 | GFP_KERNEL)); | 434 | GFP_KERNEL)); |
383 | if (!ecryptfs_superblock_to_private(sb)) { | 435 | if (!ecryptfs_superblock_to_private(sb)) { |
384 | ecryptfs_printk(KERN_WARNING, "Out of memory\n"); | 436 | ecryptfs_printk(KERN_WARNING, "Out of memory\n"); |
385 | rc = -ENOMEM; | 437 | rc = -ENOMEM; |
386 | goto out; | 438 | goto out; |
387 | } | 439 | } |
388 | memset(ecryptfs_superblock_to_private(sb), 0, | ||
389 | sizeof(struct ecryptfs_sb_info)); | ||
390 | sb->s_op = &ecryptfs_sops; | 440 | sb->s_op = &ecryptfs_sops; |
391 | /* Released through deactivate_super(sb) from get_sb_nodev */ | 441 | /* Released through deactivate_super(sb) from get_sb_nodev */ |
392 | sb->s_root = d_alloc(NULL, &(const struct qstr) { | 442 | sb->s_root = d_alloc(NULL, &(const struct qstr) { |
@@ -402,7 +452,7 @@ ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
402 | /* Released in d_release when dput(sb->s_root) is called */ | 452 | /* Released in d_release when dput(sb->s_root) is called */ |
403 | /* through deactivate_super(sb) from get_sb_nodev() */ | 453 | /* through deactivate_super(sb) from get_sb_nodev() */ |
404 | ecryptfs_set_dentry_private(sb->s_root, | 454 | ecryptfs_set_dentry_private(sb->s_root, |
405 | kmem_cache_alloc(ecryptfs_dentry_info_cache, | 455 | kmem_cache_zalloc(ecryptfs_dentry_info_cache, |
406 | GFP_KERNEL)); | 456 | GFP_KERNEL)); |
407 | if (!ecryptfs_dentry_to_private(sb->s_root)) { | 457 | if (!ecryptfs_dentry_to_private(sb->s_root)) { |
408 | ecryptfs_printk(KERN_ERR, | 458 | ecryptfs_printk(KERN_ERR, |
@@ -410,8 +460,6 @@ ecryptfs_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
410 | rc = -ENOMEM; | 460 | rc = -ENOMEM; |
411 | goto out; | 461 | goto out; |
412 | } | 462 | } |
413 | memset(ecryptfs_dentry_to_private(sb->s_root), 0, | ||
414 | sizeof(struct ecryptfs_dentry_info)); | ||
415 | rc = 0; | 463 | rc = 0; |
416 | out: | 464 | out: |
417 | /* Should be able to rely on deactivate_super called from | 465 | /* Should be able to rely on deactivate_super called from |
@@ -594,10 +642,20 @@ static struct ecryptfs_cache_info { | |||
594 | .size = PAGE_CACHE_SIZE, | 642 | .size = PAGE_CACHE_SIZE, |
595 | }, | 643 | }, |
596 | { | 644 | { |
645 | .cache = &ecryptfs_xattr_cache, | ||
646 | .name = "ecryptfs_xattr_cache", | ||
647 | .size = PAGE_CACHE_SIZE, | ||
648 | }, | ||
649 | { | ||
597 | .cache = &ecryptfs_lower_page_cache, | 650 | .cache = &ecryptfs_lower_page_cache, |
598 | .name = "ecryptfs_lower_page_cache", | 651 | .name = "ecryptfs_lower_page_cache", |
599 | .size = PAGE_CACHE_SIZE, | 652 | .size = PAGE_CACHE_SIZE, |
600 | }, | 653 | }, |
654 | { | ||
655 | .cache = &ecryptfs_key_record_cache, | ||
656 | .name = "ecryptfs_key_record_cache", | ||
657 | .size = sizeof(struct ecryptfs_key_record), | ||
658 | }, | ||
601 | }; | 659 | }; |
602 | 660 | ||
603 | static void ecryptfs_free_kmem_caches(void) | 661 | static void ecryptfs_free_kmem_caches(void) |
@@ -699,7 +757,8 @@ static struct ecryptfs_version_str_map_elem { | |||
699 | {ECRYPTFS_VERSIONING_PASSPHRASE, "passphrase"}, | 757 | {ECRYPTFS_VERSIONING_PASSPHRASE, "passphrase"}, |
700 | {ECRYPTFS_VERSIONING_PUBKEY, "pubkey"}, | 758 | {ECRYPTFS_VERSIONING_PUBKEY, "pubkey"}, |
701 | {ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"}, | 759 | {ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"}, |
702 | {ECRYPTFS_VERSIONING_POLICY, "policy"} | 760 | {ECRYPTFS_VERSIONING_POLICY, "policy"}, |
761 | {ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"} | ||
703 | }; | 762 | }; |
704 | 763 | ||
705 | static ssize_t version_str_show(struct ecryptfs_obj *obj, char *buff) | 764 | static ssize_t version_str_show(struct ecryptfs_obj *obj, char *buff) |
@@ -798,6 +857,11 @@ static int __init ecryptfs_init(void) | |||
798 | ecryptfs_free_kmem_caches(); | 857 | ecryptfs_free_kmem_caches(); |
799 | goto out; | 858 | goto out; |
800 | } | 859 | } |
860 | rc = ecryptfs_init_messaging(ecryptfs_transport); | ||
861 | if (rc) { | ||
862 | ecryptfs_printk(KERN_ERR, "Failure occured while attempting to " | ||
863 | "initialize the eCryptfs netlink socket\n"); | ||
864 | } | ||
801 | out: | 865 | out: |
802 | return rc; | 866 | return rc; |
803 | } | 867 | } |
@@ -809,6 +873,7 @@ static void __exit ecryptfs_exit(void) | |||
809 | sysfs_remove_file(&ecryptfs_subsys.kset.kobj, | 873 | sysfs_remove_file(&ecryptfs_subsys.kset.kobj, |
810 | &sysfs_attr_version_str.attr); | 874 | &sysfs_attr_version_str.attr); |
811 | subsystem_unregister(&ecryptfs_subsys); | 875 | subsystem_unregister(&ecryptfs_subsys); |
876 | ecryptfs_release_messaging(ecryptfs_transport); | ||
812 | unregister_filesystem(&ecryptfs_fs_type); | 877 | unregister_filesystem(&ecryptfs_fs_type); |
813 | ecryptfs_free_kmem_caches(); | 878 | ecryptfs_free_kmem_caches(); |
814 | } | 879 | } |
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c new file mode 100644 index 000000000000..3baf253be95a --- /dev/null +++ b/fs/ecryptfs/messaging.c | |||
@@ -0,0 +1,516 @@ | |||
1 | /** | ||
2 | * eCryptfs: Linux filesystem encryption layer | ||
3 | * | ||
4 | * Copyright (C) 2004-2006 International Business Machines Corp. | ||
5 | * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> | ||
6 | * Tyler Hicks <tyhicks@ou.edu> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version | ||
10 | * 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
20 | * 02111-1307, USA. | ||
21 | */ | ||
22 | |||
23 | #include "ecryptfs_kernel.h" | ||
24 | |||
25 | static LIST_HEAD(ecryptfs_msg_ctx_free_list); | ||
26 | static LIST_HEAD(ecryptfs_msg_ctx_alloc_list); | ||
27 | static struct mutex ecryptfs_msg_ctx_lists_mux; | ||
28 | |||
29 | static struct hlist_head *ecryptfs_daemon_id_hash; | ||
30 | static struct mutex ecryptfs_daemon_id_hash_mux; | ||
31 | static int ecryptfs_hash_buckets; | ||
32 | #define ecryptfs_uid_hash(uid) \ | ||
33 | hash_long((unsigned long)uid, ecryptfs_hash_buckets) | ||
34 | |||
35 | static unsigned int ecryptfs_msg_counter; | ||
36 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; | ||
37 | |||
38 | /** | ||
39 | * ecryptfs_acquire_free_msg_ctx | ||
40 | * @msg_ctx: The context that was acquired from the free list | ||
41 | * | ||
42 | * Acquires a context element from the free list and locks the mutex | ||
43 | * on the context. Returns zero on success; non-zero on error or upon | ||
44 | * failure to acquire a free context element. Be sure to lock the | ||
45 | * list mutex before calling. | ||
46 | */ | ||
47 | static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx) | ||
48 | { | ||
49 | struct list_head *p; | ||
50 | int rc; | ||
51 | |||
52 | if (list_empty(&ecryptfs_msg_ctx_free_list)) { | ||
53 | ecryptfs_printk(KERN_WARNING, "The eCryptfs free " | ||
54 | "context list is empty. It may be helpful to " | ||
55 | "specify the ecryptfs_message_buf_len " | ||
56 | "parameter to be greater than the current " | ||
57 | "value of [%d]\n", ecryptfs_message_buf_len); | ||
58 | rc = -ENOMEM; | ||
59 | goto out; | ||
60 | } | ||
61 | list_for_each(p, &ecryptfs_msg_ctx_free_list) { | ||
62 | *msg_ctx = list_entry(p, struct ecryptfs_msg_ctx, node); | ||
63 | if (mutex_trylock(&(*msg_ctx)->mux)) { | ||
64 | (*msg_ctx)->task = current; | ||
65 | rc = 0; | ||
66 | goto out; | ||
67 | } | ||
68 | } | ||
69 | rc = -ENOMEM; | ||
70 | out: | ||
71 | return rc; | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * ecryptfs_msg_ctx_free_to_alloc | ||
76 | * @msg_ctx: The context to move from the free list to the alloc list | ||
77 | * | ||
78 | * Be sure to lock the list mutex and the context mutex before | ||
79 | * calling. | ||
80 | */ | ||
81 | static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx) | ||
82 | { | ||
83 | list_move(&msg_ctx->node, &ecryptfs_msg_ctx_alloc_list); | ||
84 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_PENDING; | ||
85 | msg_ctx->counter = ++ecryptfs_msg_counter; | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * ecryptfs_msg_ctx_alloc_to_free | ||
90 | * @msg_ctx: The context to move from the alloc list to the free list | ||
91 | * | ||
92 | * Be sure to lock the list mutex and the context mutex before | ||
93 | * calling. | ||
94 | */ | ||
95 | static void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx) | ||
96 | { | ||
97 | list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list); | ||
98 | if (msg_ctx->msg) | ||
99 | kfree(msg_ctx->msg); | ||
100 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * ecryptfs_find_daemon_id | ||
105 | * @uid: The user id which maps to the desired daemon id | ||
106 | * @id: If return value is zero, points to the desired daemon id | ||
107 | * pointer | ||
108 | * | ||
109 | * Search the hash list for the given user id. Returns zero if the | ||
110 | * user id exists in the list; non-zero otherwise. The daemon id hash | ||
111 | * mutex should be held before calling this function. | ||
112 | */ | ||
113 | static int ecryptfs_find_daemon_id(uid_t uid, struct ecryptfs_daemon_id **id) | ||
114 | { | ||
115 | struct hlist_node *elem; | ||
116 | int rc; | ||
117 | |||
118 | hlist_for_each_entry(*id, elem, | ||
119 | &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)], | ||
120 | id_chain) { | ||
121 | if ((*id)->uid == uid) { | ||
122 | rc = 0; | ||
123 | goto out; | ||
124 | } | ||
125 | } | ||
126 | rc = -EINVAL; | ||
127 | out: | ||
128 | return rc; | ||
129 | } | ||
130 | |||
131 | static int ecryptfs_send_raw_message(unsigned int transport, u16 msg_type, | ||
132 | pid_t pid) | ||
133 | { | ||
134 | int rc; | ||
135 | |||
136 | switch(transport) { | ||
137 | case ECRYPTFS_TRANSPORT_NETLINK: | ||
138 | rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0, pid); | ||
139 | break; | ||
140 | case ECRYPTFS_TRANSPORT_CONNECTOR: | ||
141 | case ECRYPTFS_TRANSPORT_RELAYFS: | ||
142 | default: | ||
143 | rc = -ENOSYS; | ||
144 | } | ||
145 | return rc; | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * ecryptfs_process_helo | ||
150 | * @transport: The underlying transport (netlink, etc.) | ||
151 | * @uid: The user ID owner of the message | ||
152 | * @pid: The process ID for the userspace program that sent the | ||
153 | * message | ||
154 | * | ||
155 | * Adds the uid and pid values to the daemon id hash. If a uid | ||
156 | * already has a daemon pid registered, the daemon will be | ||
157 | * unregistered before the new daemon id is put into the hash list. | ||
158 | * Returns zero after adding a new daemon id to the hash list; | ||
159 | * non-zero otherwise. | ||
160 | */ | ||
161 | int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid) | ||
162 | { | ||
163 | struct ecryptfs_daemon_id *new_id; | ||
164 | struct ecryptfs_daemon_id *old_id; | ||
165 | int rc; | ||
166 | |||
167 | mutex_lock(&ecryptfs_daemon_id_hash_mux); | ||
168 | new_id = kmalloc(sizeof(*new_id), GFP_KERNEL); | ||
169 | if (!new_id) { | ||
170 | rc = -ENOMEM; | ||
171 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable " | ||
172 | "to register daemon [%d] for user [%d]\n", | ||
173 | pid, uid); | ||
174 | goto unlock; | ||
175 | } | ||
176 | if (!ecryptfs_find_daemon_id(uid, &old_id)) { | ||
177 | printk(KERN_WARNING "Received request from user [%d] " | ||
178 | "to register daemon [%d]; unregistering daemon " | ||
179 | "[%d]\n", uid, pid, old_id->pid); | ||
180 | hlist_del(&old_id->id_chain); | ||
181 | rc = ecryptfs_send_raw_message(transport, ECRYPTFS_NLMSG_QUIT, | ||
182 | old_id->pid); | ||
183 | if (rc) | ||
184 | printk(KERN_WARNING "Failed to send QUIT " | ||
185 | "message to daemon [%d]; rc = [%d]\n", | ||
186 | old_id->pid, rc); | ||
187 | kfree(old_id); | ||
188 | } | ||
189 | new_id->uid = uid; | ||
190 | new_id->pid = pid; | ||
191 | hlist_add_head(&new_id->id_chain, | ||
192 | &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)]); | ||
193 | rc = 0; | ||
194 | unlock: | ||
195 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); | ||
196 | return rc; | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * ecryptfs_process_quit | ||
201 | * @uid: The user ID owner of the message | ||
202 | * @pid: The process ID for the userspace program that sent the | ||
203 | * message | ||
204 | * | ||
205 | * Deletes the corresponding daemon id for the given uid and pid, if | ||
206 | * it is the registered that is requesting the deletion. Returns zero | ||
207 | * after deleting the desired daemon id; non-zero otherwise. | ||
208 | */ | ||
209 | int ecryptfs_process_quit(uid_t uid, pid_t pid) | ||
210 | { | ||
211 | struct ecryptfs_daemon_id *id; | ||
212 | int rc; | ||
213 | |||
214 | mutex_lock(&ecryptfs_daemon_id_hash_mux); | ||
215 | if (ecryptfs_find_daemon_id(uid, &id)) { | ||
216 | rc = -EINVAL; | ||
217 | ecryptfs_printk(KERN_ERR, "Received request from user [%d] to " | ||
218 | "unregister unrecognized daemon [%d]\n", uid, | ||
219 | pid); | ||
220 | goto unlock; | ||
221 | } | ||
222 | if (id->pid != pid) { | ||
223 | rc = -EINVAL; | ||
224 | ecryptfs_printk(KERN_WARNING, "Received request from user [%d] " | ||
225 | "with pid [%d] to unregister daemon [%d]\n", | ||
226 | uid, pid, id->pid); | ||
227 | goto unlock; | ||
228 | } | ||
229 | hlist_del(&id->id_chain); | ||
230 | kfree(id); | ||
231 | rc = 0; | ||
232 | unlock: | ||
233 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); | ||
234 | return rc; | ||
235 | } | ||
236 | |||
237 | /** | ||
238 | * ecryptfs_process_reponse | ||
239 | * @msg: The ecryptfs message received; the caller should sanity check | ||
240 | * msg->data_len | ||
241 | * @pid: The process ID of the userspace application that sent the | ||
242 | * message | ||
243 | * @seq: The sequence number of the message | ||
244 | * | ||
245 | * Processes a response message after sending a operation request to | ||
246 | * userspace. Returns zero upon delivery to desired context element; | ||
247 | * non-zero upon delivery failure or error. | ||
248 | */ | ||
249 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid, | ||
250 | pid_t pid, u32 seq) | ||
251 | { | ||
252 | struct ecryptfs_daemon_id *id; | ||
253 | struct ecryptfs_msg_ctx *msg_ctx; | ||
254 | int msg_size; | ||
255 | int rc; | ||
256 | |||
257 | if (msg->index >= ecryptfs_message_buf_len) { | ||
258 | rc = -EINVAL; | ||
259 | ecryptfs_printk(KERN_ERR, "Attempt to reference " | ||
260 | "context buffer at index [%d]; maximum " | ||
261 | "allowable is [%d]\n", msg->index, | ||
262 | (ecryptfs_message_buf_len - 1)); | ||
263 | goto out; | ||
264 | } | ||
265 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; | ||
266 | mutex_lock(&msg_ctx->mux); | ||
267 | if (ecryptfs_find_daemon_id(msg_ctx->task->euid, &id)) { | ||
268 | rc = -EBADMSG; | ||
269 | ecryptfs_printk(KERN_WARNING, "User [%d] received a " | ||
270 | "message response from process [%d] but does " | ||
271 | "not have a registered daemon\n", | ||
272 | msg_ctx->task->euid, pid); | ||
273 | goto wake_up; | ||
274 | } | ||
275 | if (msg_ctx->task->euid != uid) { | ||
276 | rc = -EBADMSG; | ||
277 | ecryptfs_printk(KERN_WARNING, "Received message from user " | ||
278 | "[%d]; expected message from user [%d]\n", | ||
279 | uid, msg_ctx->task->euid); | ||
280 | goto unlock; | ||
281 | } | ||
282 | if (id->pid != pid) { | ||
283 | rc = -EBADMSG; | ||
284 | ecryptfs_printk(KERN_ERR, "User [%d] received a " | ||
285 | "message response from an unrecognized " | ||
286 | "process [%d]\n", msg_ctx->task->euid, pid); | ||
287 | goto unlock; | ||
288 | } | ||
289 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { | ||
290 | rc = -EINVAL; | ||
291 | ecryptfs_printk(KERN_WARNING, "Desired context element is not " | ||
292 | "pending a response\n"); | ||
293 | goto unlock; | ||
294 | } else if (msg_ctx->counter != seq) { | ||
295 | rc = -EINVAL; | ||
296 | ecryptfs_printk(KERN_WARNING, "Invalid message sequence; " | ||
297 | "expected [%d]; received [%d]\n", | ||
298 | msg_ctx->counter, seq); | ||
299 | goto unlock; | ||
300 | } | ||
301 | msg_size = sizeof(*msg) + msg->data_len; | ||
302 | msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL); | ||
303 | if (!msg_ctx->msg) { | ||
304 | rc = -ENOMEM; | ||
305 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n"); | ||
306 | goto unlock; | ||
307 | } | ||
308 | memcpy(msg_ctx->msg, msg, msg_size); | ||
309 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; | ||
310 | rc = 0; | ||
311 | wake_up: | ||
312 | wake_up_process(msg_ctx->task); | ||
313 | unlock: | ||
314 | mutex_unlock(&msg_ctx->mux); | ||
315 | out: | ||
316 | return rc; | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * ecryptfs_send_message | ||
321 | * @transport: The transport over which to send the message (i.e., | ||
322 | * netlink) | ||
323 | * @data: The data to send | ||
324 | * @data_len: The length of data | ||
325 | * @msg_ctx: The message context allocated for the send | ||
326 | */ | ||
327 | int ecryptfs_send_message(unsigned int transport, char *data, int data_len, | ||
328 | struct ecryptfs_msg_ctx **msg_ctx) | ||
329 | { | ||
330 | struct ecryptfs_daemon_id *id; | ||
331 | int rc; | ||
332 | |||
333 | mutex_lock(&ecryptfs_daemon_id_hash_mux); | ||
334 | if (ecryptfs_find_daemon_id(current->euid, &id)) { | ||
335 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); | ||
336 | rc = -ENOTCONN; | ||
337 | ecryptfs_printk(KERN_ERR, "User [%d] does not have a daemon " | ||
338 | "registered\n", current->euid); | ||
339 | goto out; | ||
340 | } | ||
341 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); | ||
342 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); | ||
343 | rc = ecryptfs_acquire_free_msg_ctx(msg_ctx); | ||
344 | if (rc) { | ||
345 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); | ||
346 | ecryptfs_printk(KERN_WARNING, "Could not claim a free " | ||
347 | "context element\n"); | ||
348 | goto out; | ||
349 | } | ||
350 | ecryptfs_msg_ctx_free_to_alloc(*msg_ctx); | ||
351 | mutex_unlock(&(*msg_ctx)->mux); | ||
352 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); | ||
353 | switch (transport) { | ||
354 | case ECRYPTFS_TRANSPORT_NETLINK: | ||
355 | rc = ecryptfs_send_netlink(data, data_len, *msg_ctx, | ||
356 | ECRYPTFS_NLMSG_REQUEST, 0, id->pid); | ||
357 | break; | ||
358 | case ECRYPTFS_TRANSPORT_CONNECTOR: | ||
359 | case ECRYPTFS_TRANSPORT_RELAYFS: | ||
360 | default: | ||
361 | rc = -ENOSYS; | ||
362 | } | ||
363 | if (rc) { | ||
364 | printk(KERN_ERR "Error attempting to send message to userspace " | ||
365 | "daemon; rc = [%d]\n", rc); | ||
366 | } | ||
367 | out: | ||
368 | return rc; | ||
369 | } | ||
370 | |||
371 | /** | ||
372 | * ecryptfs_wait_for_response | ||
373 | * @msg_ctx: The context that was assigned when sending a message | ||
374 | * @msg: The incoming message from userspace; not set if rc != 0 | ||
375 | * | ||
376 | * Sleeps until awaken by ecryptfs_receive_message or until the amount | ||
377 | * of time exceeds ecryptfs_message_wait_timeout. If zero is | ||
378 | * returned, msg will point to a valid message from userspace; a | ||
379 | * non-zero value is returned upon failure to receive a message or an | ||
380 | * error occurs. | ||
381 | */ | ||
382 | int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, | ||
383 | struct ecryptfs_message **msg) | ||
384 | { | ||
385 | signed long timeout = ecryptfs_message_wait_timeout * HZ; | ||
386 | int rc = 0; | ||
387 | |||
388 | sleep: | ||
389 | timeout = schedule_timeout_interruptible(timeout); | ||
390 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); | ||
391 | mutex_lock(&msg_ctx->mux); | ||
392 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_DONE) { | ||
393 | if (timeout) { | ||
394 | mutex_unlock(&msg_ctx->mux); | ||
395 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); | ||
396 | goto sleep; | ||
397 | } | ||
398 | rc = -ENOMSG; | ||
399 | } else { | ||
400 | *msg = msg_ctx->msg; | ||
401 | msg_ctx->msg = NULL; | ||
402 | } | ||
403 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); | ||
404 | mutex_unlock(&msg_ctx->mux); | ||
405 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); | ||
406 | return rc; | ||
407 | } | ||
408 | |||
409 | int ecryptfs_init_messaging(unsigned int transport) | ||
410 | { | ||
411 | int i; | ||
412 | int rc = 0; | ||
413 | |||
414 | if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) { | ||
415 | ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS; | ||
416 | ecryptfs_printk(KERN_WARNING, "Specified number of users is " | ||
417 | "too large, defaulting to [%d] users\n", | ||
418 | ecryptfs_number_of_users); | ||
419 | } | ||
420 | mutex_init(&ecryptfs_daemon_id_hash_mux); | ||
421 | mutex_lock(&ecryptfs_daemon_id_hash_mux); | ||
422 | ecryptfs_hash_buckets = 0; | ||
423 | while (ecryptfs_number_of_users >> ++ecryptfs_hash_buckets); | ||
424 | ecryptfs_daemon_id_hash = kmalloc(sizeof(struct hlist_head) | ||
425 | * ecryptfs_hash_buckets, GFP_KERNEL); | ||
426 | if (!ecryptfs_daemon_id_hash) { | ||
427 | rc = -ENOMEM; | ||
428 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n"); | ||
429 | goto out; | ||
430 | } | ||
431 | for (i = 0; i < ecryptfs_hash_buckets; i++) | ||
432 | INIT_HLIST_HEAD(&ecryptfs_daemon_id_hash[i]); | ||
433 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); | ||
434 | |||
435 | ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx) | ||
436 | * ecryptfs_message_buf_len), GFP_KERNEL); | ||
437 | if (!ecryptfs_msg_ctx_arr) { | ||
438 | rc = -ENOMEM; | ||
439 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n"); | ||
440 | goto out; | ||
441 | } | ||
442 | mutex_init(&ecryptfs_msg_ctx_lists_mux); | ||
443 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); | ||
444 | ecryptfs_msg_counter = 0; | ||
445 | for (i = 0; i < ecryptfs_message_buf_len; i++) { | ||
446 | INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node); | ||
447 | mutex_init(&ecryptfs_msg_ctx_arr[i].mux); | ||
448 | mutex_lock(&ecryptfs_msg_ctx_arr[i].mux); | ||
449 | ecryptfs_msg_ctx_arr[i].index = i; | ||
450 | ecryptfs_msg_ctx_arr[i].state = ECRYPTFS_MSG_CTX_STATE_FREE; | ||
451 | ecryptfs_msg_ctx_arr[i].counter = 0; | ||
452 | ecryptfs_msg_ctx_arr[i].task = NULL; | ||
453 | ecryptfs_msg_ctx_arr[i].msg = NULL; | ||
454 | list_add_tail(&ecryptfs_msg_ctx_arr[i].node, | ||
455 | &ecryptfs_msg_ctx_free_list); | ||
456 | mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux); | ||
457 | } | ||
458 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); | ||
459 | switch(transport) { | ||
460 | case ECRYPTFS_TRANSPORT_NETLINK: | ||
461 | rc = ecryptfs_init_netlink(); | ||
462 | if (rc) | ||
463 | ecryptfs_release_messaging(transport); | ||
464 | break; | ||
465 | case ECRYPTFS_TRANSPORT_CONNECTOR: | ||
466 | case ECRYPTFS_TRANSPORT_RELAYFS: | ||
467 | default: | ||
468 | rc = -ENOSYS; | ||
469 | } | ||
470 | out: | ||
471 | return rc; | ||
472 | } | ||
473 | |||
474 | void ecryptfs_release_messaging(unsigned int transport) | ||
475 | { | ||
476 | if (ecryptfs_msg_ctx_arr) { | ||
477 | int i; | ||
478 | |||
479 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); | ||
480 | for (i = 0; i < ecryptfs_message_buf_len; i++) { | ||
481 | mutex_lock(&ecryptfs_msg_ctx_arr[i].mux); | ||
482 | if (ecryptfs_msg_ctx_arr[i].msg) | ||
483 | kfree(ecryptfs_msg_ctx_arr[i].msg); | ||
484 | mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux); | ||
485 | } | ||
486 | kfree(ecryptfs_msg_ctx_arr); | ||
487 | mutex_unlock(&ecryptfs_msg_ctx_lists_mux); | ||
488 | } | ||
489 | if (ecryptfs_daemon_id_hash) { | ||
490 | struct hlist_node *elem; | ||
491 | struct ecryptfs_daemon_id *id; | ||
492 | int i; | ||
493 | |||
494 | mutex_lock(&ecryptfs_daemon_id_hash_mux); | ||
495 | for (i = 0; i < ecryptfs_hash_buckets; i++) { | ||
496 | hlist_for_each_entry(id, elem, | ||
497 | &ecryptfs_daemon_id_hash[i], | ||
498 | id_chain) { | ||
499 | hlist_del(elem); | ||
500 | kfree(id); | ||
501 | } | ||
502 | } | ||
503 | kfree(ecryptfs_daemon_id_hash); | ||
504 | mutex_unlock(&ecryptfs_daemon_id_hash_mux); | ||
505 | } | ||
506 | switch(transport) { | ||
507 | case ECRYPTFS_TRANSPORT_NETLINK: | ||
508 | ecryptfs_release_netlink(); | ||
509 | break; | ||
510 | case ECRYPTFS_TRANSPORT_CONNECTOR: | ||
511 | case ECRYPTFS_TRANSPORT_RELAYFS: | ||
512 | default: | ||
513 | break; | ||
514 | } | ||
515 | return; | ||
516 | } | ||
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 06843d24f239..3a6f65c3f14f 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Copyright (C) 1997-2003 Erez Zadok | 7 | * Copyright (C) 1997-2003 Erez Zadok |
8 | * Copyright (C) 2001-2003 Stony Brook University | 8 | * Copyright (C) 2001-2003 Stony Brook University |
9 | * Copyright (C) 2004-2006 International Business Machines Corp. | 9 | * Copyright (C) 2004-2007 International Business Machines Corp. |
10 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 10 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
@@ -234,22 +234,13 @@ int ecryptfs_do_readpage(struct file *file, struct page *page, | |||
234 | goto out; | 234 | goto out; |
235 | } | 235 | } |
236 | wait_on_page_locked(lower_page); | 236 | wait_on_page_locked(lower_page); |
237 | page_data = (char *)kmap(page); | 237 | page_data = kmap_atomic(page, KM_USER0); |
238 | if (!page_data) { | 238 | lower_page_data = kmap_atomic(lower_page, KM_USER1); |
239 | rc = -ENOMEM; | ||
240 | ecryptfs_printk(KERN_ERR, "Error mapping page\n"); | ||
241 | goto out; | ||
242 | } | ||
243 | lower_page_data = (char *)kmap(lower_page); | ||
244 | if (!lower_page_data) { | ||
245 | rc = -ENOMEM; | ||
246 | ecryptfs_printk(KERN_ERR, "Error mapping page\n"); | ||
247 | kunmap(page); | ||
248 | goto out; | ||
249 | } | ||
250 | memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE); | 239 | memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE); |
251 | kunmap(lower_page); | 240 | kunmap_atomic(lower_page_data, KM_USER1); |
252 | kunmap(page); | 241 | flush_dcache_page(lower_page); |
242 | kunmap_atomic(page_data, KM_USER0); | ||
243 | flush_dcache_page(page); | ||
253 | rc = 0; | 244 | rc = 0; |
254 | out: | 245 | out: |
255 | if (likely(lower_page)) | 246 | if (likely(lower_page)) |
@@ -260,6 +251,33 @@ out: | |||
260 | ClearPageUptodate(page); | 251 | ClearPageUptodate(page); |
261 | return rc; | 252 | return rc; |
262 | } | 253 | } |
254 | /** | ||
255 | * Header Extent: | ||
256 | * Octets 0-7: Unencrypted file size (big-endian) | ||
257 | * Octets 8-15: eCryptfs special marker | ||
258 | * Octets 16-19: Flags | ||
259 | * Octet 16: File format version number (between 0 and 255) | ||
260 | * Octets 17-18: Reserved | ||
261 | * Octet 19: Bit 1 (lsb): Reserved | ||
262 | * Bit 2: Encrypted? | ||
263 | * Bits 3-8: Reserved | ||
264 | * Octets 20-23: Header extent size (big-endian) | ||
265 | * Octets 24-25: Number of header extents at front of file | ||
266 | * (big-endian) | ||
267 | * Octet 26: Begin RFC 2440 authentication token packet set | ||
268 | */ | ||
269 | static void set_header_info(char *page_virt, | ||
270 | struct ecryptfs_crypt_stat *crypt_stat) | ||
271 | { | ||
272 | size_t written; | ||
273 | int save_num_header_extents_at_front = | ||
274 | crypt_stat->num_header_extents_at_front; | ||
275 | |||
276 | crypt_stat->num_header_extents_at_front = 1; | ||
277 | ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written); | ||
278 | crypt_stat->num_header_extents_at_front = | ||
279 | save_num_header_extents_at_front; | ||
280 | } | ||
263 | 281 | ||
264 | /** | 282 | /** |
265 | * ecryptfs_readpage | 283 | * ecryptfs_readpage |
@@ -279,8 +297,8 @@ static int ecryptfs_readpage(struct file *file, struct page *page) | |||
279 | crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) | 297 | crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) |
280 | ->crypt_stat; | 298 | ->crypt_stat; |
281 | if (!crypt_stat | 299 | if (!crypt_stat |
282 | || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED) | 300 | || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED) |
283 | || ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) { | 301 | || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { |
284 | ecryptfs_printk(KERN_DEBUG, | 302 | ecryptfs_printk(KERN_DEBUG, |
285 | "Passing through unencrypted page\n"); | 303 | "Passing through unencrypted page\n"); |
286 | rc = ecryptfs_do_readpage(file, page, page->index); | 304 | rc = ecryptfs_do_readpage(file, page, page->index); |
@@ -289,10 +307,51 @@ static int ecryptfs_readpage(struct file *file, struct page *page) | |||
289 | "[%d]\n", rc); | 307 | "[%d]\n", rc); |
290 | goto out; | 308 | goto out; |
291 | } | 309 | } |
310 | } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { | ||
311 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { | ||
312 | int num_pages_in_header_region = | ||
313 | (crypt_stat->header_extent_size | ||
314 | / PAGE_CACHE_SIZE); | ||
315 | |||
316 | if (page->index < num_pages_in_header_region) { | ||
317 | char *page_virt; | ||
318 | |||
319 | page_virt = kmap_atomic(page, KM_USER0); | ||
320 | memset(page_virt, 0, PAGE_CACHE_SIZE); | ||
321 | if (page->index == 0) { | ||
322 | rc = ecryptfs_read_xattr_region( | ||
323 | page_virt, file->f_path.dentry); | ||
324 | set_header_info(page_virt, crypt_stat); | ||
325 | } | ||
326 | kunmap_atomic(page_virt, KM_USER0); | ||
327 | flush_dcache_page(page); | ||
328 | if (rc) { | ||
329 | printk(KERN_ERR "Error reading xattr " | ||
330 | "region\n"); | ||
331 | goto out; | ||
332 | } | ||
333 | } else { | ||
334 | rc = ecryptfs_do_readpage( | ||
335 | file, page, | ||
336 | (page->index | ||
337 | - num_pages_in_header_region)); | ||
338 | if (rc) { | ||
339 | printk(KERN_ERR "Error reading page; " | ||
340 | "rc = [%d]\n", rc); | ||
341 | goto out; | ||
342 | } | ||
343 | } | ||
344 | } else { | ||
345 | rc = ecryptfs_do_readpage(file, page, page->index); | ||
346 | if (rc) { | ||
347 | printk(KERN_ERR "Error reading page; rc = " | ||
348 | "[%d]\n", rc); | ||
349 | goto out; | ||
350 | } | ||
351 | } | ||
292 | } else { | 352 | } else { |
293 | rc = ecryptfs_decrypt_page(file, page); | 353 | rc = ecryptfs_decrypt_page(file, page); |
294 | if (rc) { | 354 | if (rc) { |
295 | |||
296 | ecryptfs_printk(KERN_ERR, "Error decrypting page; " | 355 | ecryptfs_printk(KERN_ERR, "Error decrypting page; " |
297 | "rc = [%d]\n", rc); | 356 | "rc = [%d]\n", rc); |
298 | goto out; | 357 | goto out; |
@@ -308,30 +367,27 @@ out: | |||
308 | return rc; | 367 | return rc; |
309 | } | 368 | } |
310 | 369 | ||
370 | /** | ||
371 | * Called with lower inode mutex held. | ||
372 | */ | ||
311 | static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) | 373 | static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) |
312 | { | 374 | { |
313 | struct inode *inode = page->mapping->host; | 375 | struct inode *inode = page->mapping->host; |
314 | int end_byte_in_page; | 376 | int end_byte_in_page; |
315 | int rc = 0; | ||
316 | char *page_virt; | 377 | char *page_virt; |
317 | 378 | ||
318 | if ((i_size_read(inode) / PAGE_CACHE_SIZE) == page->index) { | 379 | if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index) |
319 | end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; | 380 | goto out; |
320 | if (to > end_byte_in_page) | 381 | end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; |
321 | end_byte_in_page = to; | 382 | if (to > end_byte_in_page) |
322 | page_virt = kmap(page); | 383 | end_byte_in_page = to; |
323 | if (!page_virt) { | 384 | page_virt = kmap_atomic(page, KM_USER0); |
324 | rc = -ENOMEM; | 385 | memset((page_virt + end_byte_in_page), 0, |
325 | ecryptfs_printk(KERN_WARNING, | 386 | (PAGE_CACHE_SIZE - end_byte_in_page)); |
326 | "Could not map page\n"); | 387 | kunmap_atomic(page_virt, KM_USER0); |
327 | goto out; | 388 | flush_dcache_page(page); |
328 | } | ||
329 | memset((page_virt + end_byte_in_page), 0, | ||
330 | (PAGE_CACHE_SIZE - end_byte_in_page)); | ||
331 | kunmap(page); | ||
332 | } | ||
333 | out: | 389 | out: |
334 | return rc; | 390 | return 0; |
335 | } | 391 | } |
336 | 392 | ||
337 | static int ecryptfs_prepare_write(struct file *file, struct page *page, | 393 | static int ecryptfs_prepare_write(struct file *file, struct page *page, |
@@ -339,7 +395,6 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page, | |||
339 | { | 395 | { |
340 | int rc = 0; | 396 | int rc = 0; |
341 | 397 | ||
342 | kmap(page); | ||
343 | if (from == 0 && to == PAGE_CACHE_SIZE) | 398 | if (from == 0 && to == PAGE_CACHE_SIZE) |
344 | goto out; /* If we are writing a full page, it will be | 399 | goto out; /* If we are writing a full page, it will be |
345 | up to date. */ | 400 | up to date. */ |
@@ -349,30 +404,6 @@ out: | |||
349 | return rc; | 404 | return rc; |
350 | } | 405 | } |
351 | 406 | ||
352 | int ecryptfs_grab_and_map_lower_page(struct page **lower_page, | ||
353 | char **lower_virt, | ||
354 | struct inode *lower_inode, | ||
355 | unsigned long lower_page_index) | ||
356 | { | ||
357 | int rc = 0; | ||
358 | |||
359 | (*lower_page) = grab_cache_page(lower_inode->i_mapping, | ||
360 | lower_page_index); | ||
361 | if (!(*lower_page)) { | ||
362 | ecryptfs_printk(KERN_ERR, "grab_cache_page for " | ||
363 | "lower_page_index = [0x%.16x] failed\n", | ||
364 | lower_page_index); | ||
365 | rc = -EINVAL; | ||
366 | goto out; | ||
367 | } | ||
368 | if (lower_virt) | ||
369 | (*lower_virt) = kmap((*lower_page)); | ||
370 | else | ||
371 | kmap((*lower_page)); | ||
372 | out: | ||
373 | return rc; | ||
374 | } | ||
375 | |||
376 | int ecryptfs_writepage_and_release_lower_page(struct page *lower_page, | 407 | int ecryptfs_writepage_and_release_lower_page(struct page *lower_page, |
377 | struct inode *lower_inode, | 408 | struct inode *lower_inode, |
378 | struct writeback_control *wbc) | 409 | struct writeback_control *wbc) |
@@ -391,11 +422,8 @@ out: | |||
391 | return rc; | 422 | return rc; |
392 | } | 423 | } |
393 | 424 | ||
394 | static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page) | 425 | static void ecryptfs_release_lower_page(struct page *lower_page) |
395 | { | 426 | { |
396 | kunmap(lower_page); | ||
397 | ecryptfs_printk(KERN_DEBUG, "Unlocking lower page with index = " | ||
398 | "[0x%.16x]\n", lower_page->index); | ||
399 | unlock_page(lower_page); | 427 | unlock_page(lower_page); |
400 | page_cache_release(lower_page); | 428 | page_cache_release(lower_page); |
401 | } | 429 | } |
@@ -407,10 +435,9 @@ static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page) | |||
407 | * | 435 | * |
408 | * Returns zero on success; non-zero on error. | 436 | * Returns zero on success; non-zero on error. |
409 | */ | 437 | */ |
410 | int | 438 | static int ecryptfs_write_inode_size_to_header(struct file *lower_file, |
411 | ecryptfs_write_inode_size_to_header(struct file *lower_file, | 439 | struct inode *lower_inode, |
412 | struct inode *lower_inode, | 440 | struct inode *inode) |
413 | struct inode *inode) | ||
414 | { | 441 | { |
415 | int rc = 0; | 442 | int rc = 0; |
416 | struct page *header_page; | 443 | struct page *header_page; |
@@ -418,11 +445,11 @@ ecryptfs_write_inode_size_to_header(struct file *lower_file, | |||
418 | const struct address_space_operations *lower_a_ops; | 445 | const struct address_space_operations *lower_a_ops; |
419 | u64 file_size; | 446 | u64 file_size; |
420 | 447 | ||
421 | rc = ecryptfs_grab_and_map_lower_page(&header_page, &header_virt, | 448 | header_page = grab_cache_page(lower_inode->i_mapping, 0); |
422 | lower_inode, 0); | 449 | if (!header_page) { |
423 | if (rc) { | 450 | ecryptfs_printk(KERN_ERR, "grab_cache_page for " |
424 | ecryptfs_printk(KERN_ERR, "grab_cache_page for header page " | 451 | "lower_page_index 0 failed\n"); |
425 | "failed\n"); | 452 | rc = -EINVAL; |
426 | goto out; | 453 | goto out; |
427 | } | 454 | } |
428 | lower_a_ops = lower_inode->i_mapping->a_ops; | 455 | lower_a_ops = lower_inode->i_mapping->a_ops; |
@@ -430,18 +457,95 @@ ecryptfs_write_inode_size_to_header(struct file *lower_file, | |||
430 | file_size = (u64)i_size_read(inode); | 457 | file_size = (u64)i_size_read(inode); |
431 | ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size); | 458 | ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size); |
432 | file_size = cpu_to_be64(file_size); | 459 | file_size = cpu_to_be64(file_size); |
460 | header_virt = kmap_atomic(header_page, KM_USER0); | ||
433 | memcpy(header_virt, &file_size, sizeof(u64)); | 461 | memcpy(header_virt, &file_size, sizeof(u64)); |
462 | kunmap_atomic(header_virt, KM_USER0); | ||
463 | flush_dcache_page(header_page); | ||
434 | rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8); | 464 | rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8); |
435 | if (rc < 0) | 465 | if (rc < 0) |
436 | ecryptfs_printk(KERN_ERR, "Error commiting header page " | 466 | ecryptfs_printk(KERN_ERR, "Error commiting header page " |
437 | "write\n"); | 467 | "write\n"); |
438 | ecryptfs_unmap_and_release_lower_page(header_page); | 468 | ecryptfs_release_lower_page(header_page); |
439 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; | 469 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; |
440 | mark_inode_dirty_sync(inode); | 470 | mark_inode_dirty_sync(inode); |
441 | out: | 471 | out: |
442 | return rc; | 472 | return rc; |
443 | } | 473 | } |
444 | 474 | ||
475 | static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode, | ||
476 | struct inode *inode, | ||
477 | struct dentry *ecryptfs_dentry, | ||
478 | int lower_i_mutex_held) | ||
479 | { | ||
480 | ssize_t size; | ||
481 | void *xattr_virt; | ||
482 | struct dentry *lower_dentry; | ||
483 | u64 file_size; | ||
484 | int rc; | ||
485 | |||
486 | xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL); | ||
487 | if (!xattr_virt) { | ||
488 | printk(KERN_ERR "Out of memory whilst attempting to write " | ||
489 | "inode size to xattr\n"); | ||
490 | rc = -ENOMEM; | ||
491 | goto out; | ||
492 | } | ||
493 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); | ||
494 | if (!lower_dentry->d_inode->i_op->getxattr) { | ||
495 | printk(KERN_WARNING | ||
496 | "No support for setting xattr in lower filesystem\n"); | ||
497 | rc = -ENOSYS; | ||
498 | kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); | ||
499 | goto out; | ||
500 | } | ||
501 | if (!lower_i_mutex_held) | ||
502 | mutex_lock(&lower_dentry->d_inode->i_mutex); | ||
503 | size = lower_dentry->d_inode->i_op->getxattr(lower_dentry, | ||
504 | ECRYPTFS_XATTR_NAME, | ||
505 | xattr_virt, | ||
506 | PAGE_CACHE_SIZE); | ||
507 | if (!lower_i_mutex_held) | ||
508 | mutex_unlock(&lower_dentry->d_inode->i_mutex); | ||
509 | if (size < 0) | ||
510 | size = 8; | ||
511 | file_size = (u64)i_size_read(inode); | ||
512 | file_size = cpu_to_be64(file_size); | ||
513 | memcpy(xattr_virt, &file_size, sizeof(u64)); | ||
514 | if (!lower_i_mutex_held) | ||
515 | mutex_lock(&lower_dentry->d_inode->i_mutex); | ||
516 | rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry, | ||
517 | ECRYPTFS_XATTR_NAME, | ||
518 | xattr_virt, size, 0); | ||
519 | if (!lower_i_mutex_held) | ||
520 | mutex_unlock(&lower_dentry->d_inode->i_mutex); | ||
521 | if (rc) | ||
522 | printk(KERN_ERR "Error whilst attempting to write inode size " | ||
523 | "to lower file xattr; rc = [%d]\n", rc); | ||
524 | kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); | ||
525 | out: | ||
526 | return rc; | ||
527 | } | ||
528 | |||
529 | int | ||
530 | ecryptfs_write_inode_size_to_metadata(struct file *lower_file, | ||
531 | struct inode *lower_inode, | ||
532 | struct inode *inode, | ||
533 | struct dentry *ecryptfs_dentry, | ||
534 | int lower_i_mutex_held) | ||
535 | { | ||
536 | struct ecryptfs_crypt_stat *crypt_stat; | ||
537 | |||
538 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; | ||
539 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | ||
540 | return ecryptfs_write_inode_size_to_xattr(lower_inode, inode, | ||
541 | ecryptfs_dentry, | ||
542 | lower_i_mutex_held); | ||
543 | else | ||
544 | return ecryptfs_write_inode_size_to_header(lower_file, | ||
545 | lower_inode, | ||
546 | inode); | ||
547 | } | ||
548 | |||
445 | int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, | 549 | int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, |
446 | struct file *lower_file, | 550 | struct file *lower_file, |
447 | unsigned long lower_page_index, int byte_offset, | 551 | unsigned long lower_page_index, int byte_offset, |
@@ -449,10 +553,10 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, | |||
449 | { | 553 | { |
450 | int rc = 0; | 554 | int rc = 0; |
451 | 555 | ||
452 | rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL, lower_inode, | 556 | *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index); |
453 | lower_page_index); | 557 | if (!(*lower_page)) { |
454 | if (rc) { | 558 | rc = -EINVAL; |
455 | ecryptfs_printk(KERN_ERR, "Error attempting to grab and map " | 559 | ecryptfs_printk(KERN_ERR, "Error attempting to grab " |
456 | "lower page with index [0x%.16x]\n", | 560 | "lower page with index [0x%.16x]\n", |
457 | lower_page_index); | 561 | lower_page_index); |
458 | goto out; | 562 | goto out; |
@@ -468,7 +572,7 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, | |||
468 | } | 572 | } |
469 | out: | 573 | out: |
470 | if (rc && (*lower_page)) { | 574 | if (rc && (*lower_page)) { |
471 | ecryptfs_unmap_and_release_lower_page(*lower_page); | 575 | ecryptfs_release_lower_page(*lower_page); |
472 | (*lower_page) = NULL; | 576 | (*lower_page) = NULL; |
473 | } | 577 | } |
474 | return rc; | 578 | return rc; |
@@ -493,7 +597,7 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode, | |||
493 | "Error committing write; rc = [%d]\n", rc); | 597 | "Error committing write; rc = [%d]\n", rc); |
494 | } else | 598 | } else |
495 | rc = 0; | 599 | rc = 0; |
496 | ecryptfs_unmap_and_release_lower_page(lower_page); | 600 | ecryptfs_release_lower_page(lower_page); |
497 | return rc; | 601 | return rc; |
498 | } | 602 | } |
499 | 603 | ||
@@ -528,89 +632,7 @@ out: | |||
528 | return rc; | 632 | return rc; |
529 | } | 633 | } |
530 | 634 | ||
531 | static int | 635 | struct kmem_cache *ecryptfs_xattr_cache; |
532 | process_new_file(struct ecryptfs_crypt_stat *crypt_stat, | ||
533 | struct file *file, struct inode *inode) | ||
534 | { | ||
535 | struct page *header_page; | ||
536 | const struct address_space_operations *lower_a_ops; | ||
537 | struct inode *lower_inode; | ||
538 | struct file *lower_file; | ||
539 | char *header_virt; | ||
540 | int rc = 0; | ||
541 | int current_header_page = 0; | ||
542 | int header_pages; | ||
543 | int more_header_data_to_be_written = 1; | ||
544 | |||
545 | lower_inode = ecryptfs_inode_to_lower(inode); | ||
546 | lower_file = ecryptfs_file_to_lower(file); | ||
547 | lower_a_ops = lower_inode->i_mapping->a_ops; | ||
548 | header_pages = ((crypt_stat->header_extent_size | ||
549 | * crypt_stat->num_header_extents_at_front) | ||
550 | / PAGE_CACHE_SIZE); | ||
551 | BUG_ON(header_pages < 1); | ||
552 | while (current_header_page < header_pages) { | ||
553 | rc = ecryptfs_grab_and_map_lower_page(&header_page, | ||
554 | &header_virt, | ||
555 | lower_inode, | ||
556 | current_header_page); | ||
557 | if (rc) { | ||
558 | ecryptfs_printk(KERN_ERR, "grab_cache_page for " | ||
559 | "header page [%d] failed; rc = [%d]\n", | ||
560 | current_header_page, rc); | ||
561 | goto out; | ||
562 | } | ||
563 | rc = lower_a_ops->prepare_write(lower_file, header_page, 0, | ||
564 | PAGE_CACHE_SIZE); | ||
565 | if (rc) { | ||
566 | ecryptfs_printk(KERN_ERR, "Error preparing to write " | ||
567 | "header page out; rc = [%d]\n", rc); | ||
568 | goto out; | ||
569 | } | ||
570 | memset(header_virt, 0, PAGE_CACHE_SIZE); | ||
571 | if (more_header_data_to_be_written) { | ||
572 | rc = ecryptfs_write_headers_virt(header_virt, | ||
573 | crypt_stat, | ||
574 | file->f_dentry); | ||
575 | if (rc) { | ||
576 | ecryptfs_printk(KERN_WARNING, "Error " | ||
577 | "generating header; rc = " | ||
578 | "[%d]\n", rc); | ||
579 | rc = -EIO; | ||
580 | memset(header_virt, 0, PAGE_CACHE_SIZE); | ||
581 | ecryptfs_unmap_and_release_lower_page( | ||
582 | header_page); | ||
583 | goto out; | ||
584 | } | ||
585 | if (current_header_page == 0) | ||
586 | memset(header_virt, 0, 8); | ||
587 | more_header_data_to_be_written = 0; | ||
588 | } | ||
589 | rc = lower_a_ops->commit_write(lower_file, header_page, 0, | ||
590 | PAGE_CACHE_SIZE); | ||
591 | ecryptfs_unmap_and_release_lower_page(header_page); | ||
592 | if (rc < 0) { | ||
593 | ecryptfs_printk(KERN_ERR, | ||
594 | "Error commiting header page write; " | ||
595 | "rc = [%d]\n", rc); | ||
596 | break; | ||
597 | } | ||
598 | current_header_page++; | ||
599 | } | ||
600 | if (rc >= 0) { | ||
601 | rc = 0; | ||
602 | ecryptfs_printk(KERN_DEBUG, "lower_inode->i_blocks = " | ||
603 | "[0x%.16x]\n", lower_inode->i_blocks); | ||
604 | i_size_write(inode, 0); | ||
605 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; | ||
606 | mark_inode_dirty_sync(inode); | ||
607 | } | ||
608 | ecryptfs_printk(KERN_DEBUG, "Clearing ECRYPTFS_NEW_FILE flag in " | ||
609 | "crypt_stat at memory location [%p]\n", crypt_stat); | ||
610 | ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE); | ||
611 | out: | ||
612 | return rc; | ||
613 | } | ||
614 | 636 | ||
615 | /** | 637 | /** |
616 | * ecryptfs_commit_write | 638 | * ecryptfs_commit_write |
@@ -640,15 +662,10 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, | |||
640 | mutex_lock(&lower_inode->i_mutex); | 662 | mutex_lock(&lower_inode->i_mutex); |
641 | crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) | 663 | crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) |
642 | ->crypt_stat; | 664 | ->crypt_stat; |
643 | if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) { | 665 | if (crypt_stat->flags & ECRYPTFS_NEW_FILE) { |
644 | ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in " | 666 | ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in " |
645 | "crypt_stat at memory location [%p]\n", crypt_stat); | 667 | "crypt_stat at memory location [%p]\n", crypt_stat); |
646 | rc = process_new_file(crypt_stat, file, inode); | 668 | crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE); |
647 | if (rc) { | ||
648 | ecryptfs_printk(KERN_ERR, "Error processing new " | ||
649 | "file; rc = [%d]\n", rc); | ||
650 | goto out; | ||
651 | } | ||
652 | } else | 669 | } else |
653 | ecryptfs_printk(KERN_DEBUG, "Not a new file\n"); | 670 | ecryptfs_printk(KERN_DEBUG, "Not a new file\n"); |
654 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" | 671 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" |
@@ -670,7 +687,6 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, | |||
670 | "index [0x%.16x])\n", page->index); | 687 | "index [0x%.16x])\n", page->index); |
671 | goto out; | 688 | goto out; |
672 | } | 689 | } |
673 | rc = 0; | ||
674 | inode->i_blocks = lower_inode->i_blocks; | 690 | inode->i_blocks = lower_inode->i_blocks; |
675 | pos = (page->index << PAGE_CACHE_SHIFT) + to; | 691 | pos = (page->index << PAGE_CACHE_SHIFT) + to; |
676 | if (pos > i_size_read(inode)) { | 692 | if (pos > i_size_read(inode)) { |
@@ -678,11 +694,15 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, | |||
678 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " | 694 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " |
679 | "[0x%.16x]\n", i_size_read(inode)); | 695 | "[0x%.16x]\n", i_size_read(inode)); |
680 | } | 696 | } |
681 | ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode); | 697 | rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, |
698 | inode, file->f_dentry, | ||
699 | ECRYPTFS_LOWER_I_MUTEX_HELD); | ||
700 | if (rc) | ||
701 | printk(KERN_ERR "Error writing inode size to metadata; " | ||
702 | "rc = [%d]\n", rc); | ||
682 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; | 703 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; |
683 | mark_inode_dirty_sync(inode); | 704 | mark_inode_dirty_sync(inode); |
684 | out: | 705 | out: |
685 | kunmap(page); /* mapped in prior call (prepare_write) */ | ||
686 | if (rc < 0) | 706 | if (rc < 0) |
687 | ClearPageUptodate(page); | 707 | ClearPageUptodate(page); |
688 | else | 708 | else |
@@ -707,6 +727,7 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) | |||
707 | { | 727 | { |
708 | int rc = 0; | 728 | int rc = 0; |
709 | struct page *tmp_page; | 729 | struct page *tmp_page; |
730 | char *tmp_page_virt; | ||
710 | 731 | ||
711 | tmp_page = ecryptfs_get1page(file, index); | 732 | tmp_page = ecryptfs_get1page(file, index); |
712 | if (IS_ERR(tmp_page)) { | 733 | if (IS_ERR(tmp_page)) { |
@@ -715,28 +736,27 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) | |||
715 | rc = PTR_ERR(tmp_page); | 736 | rc = PTR_ERR(tmp_page); |
716 | goto out; | 737 | goto out; |
717 | } | 738 | } |
718 | kmap(tmp_page); | ||
719 | rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros); | 739 | rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros); |
720 | if (rc) { | 740 | if (rc) { |
721 | ecryptfs_printk(KERN_ERR, "Error preparing to write zero's " | 741 | ecryptfs_printk(KERN_ERR, "Error preparing to write zero's " |
722 | "to remainder of page at index [0x%.16x]\n", | 742 | "to remainder of page at index [0x%.16x]\n", |
723 | index); | 743 | index); |
724 | kunmap(tmp_page); | ||
725 | page_cache_release(tmp_page); | 744 | page_cache_release(tmp_page); |
726 | goto out; | 745 | goto out; |
727 | } | 746 | } |
728 | memset(((char *)page_address(tmp_page) + start), 0, num_zeros); | 747 | tmp_page_virt = kmap_atomic(tmp_page, KM_USER0); |
748 | memset(((char *)tmp_page_virt + start), 0, num_zeros); | ||
749 | kunmap_atomic(tmp_page_virt, KM_USER0); | ||
750 | flush_dcache_page(tmp_page); | ||
729 | rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros); | 751 | rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros); |
730 | if (rc < 0) { | 752 | if (rc < 0) { |
731 | ecryptfs_printk(KERN_ERR, "Error attempting to write zero's " | 753 | ecryptfs_printk(KERN_ERR, "Error attempting to write zero's " |
732 | "to remainder of page at index [0x%.16x]\n", | 754 | "to remainder of page at index [0x%.16x]\n", |
733 | index); | 755 | index); |
734 | kunmap(tmp_page); | ||
735 | page_cache_release(tmp_page); | 756 | page_cache_release(tmp_page); |
736 | goto out; | 757 | goto out; |
737 | } | 758 | } |
738 | rc = 0; | 759 | rc = 0; |
739 | kunmap(tmp_page); | ||
740 | page_cache_release(tmp_page); | 760 | page_cache_release(tmp_page); |
741 | out: | 761 | out: |
742 | return rc; | 762 | return rc; |
diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c new file mode 100644 index 000000000000..e3aa2253c850 --- /dev/null +++ b/fs/ecryptfs/netlink.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /** | ||
2 | * eCryptfs: Linux filesystem encryption layer | ||
3 | * | ||
4 | * Copyright (C) 2004-2006 International Business Machines Corp. | ||
5 | * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> | ||
6 | * Tyler Hicks <tyhicks@ou.edu> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version | ||
10 | * 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
20 | * 02111-1307, USA. | ||
21 | */ | ||
22 | |||
23 | #include <net/sock.h> | ||
24 | #include <linux/hash.h> | ||
25 | #include <linux/random.h> | ||
26 | #include "ecryptfs_kernel.h" | ||
27 | |||
28 | static struct sock *ecryptfs_nl_sock; | ||
29 | |||
30 | /** | ||
31 | * ecryptfs_send_netlink | ||
32 | * @data: The data to include as the payload | ||
33 | * @data_len: The byte count of the data | ||
34 | * @msg_ctx: The netlink context that will be used to handle the | ||
35 | * response message | ||
36 | * @msg_type: The type of netlink message to send | ||
37 | * @msg_flags: The flags to include in the netlink header | ||
38 | * @daemon_pid: The process id of the daemon to send the message to | ||
39 | * | ||
40 | * Sends the data to the specified daemon pid and uses the netlink | ||
41 | * context element to store the data needed for validation upon | ||
42 | * receiving the response. The data and the netlink context can be | ||
43 | * null if just sending a netlink header is sufficient. Returns zero | ||
44 | * upon sending the message; non-zero upon error. | ||
45 | */ | ||
46 | int ecryptfs_send_netlink(char *data, int data_len, | ||
47 | struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type, | ||
48 | u16 msg_flags, pid_t daemon_pid) | ||
49 | { | ||
50 | struct sk_buff *skb; | ||
51 | struct nlmsghdr *nlh; | ||
52 | struct ecryptfs_message *msg; | ||
53 | size_t payload_len; | ||
54 | int rc; | ||
55 | |||
56 | payload_len = ((data && data_len) ? (sizeof(*msg) + data_len) : 0); | ||
57 | skb = alloc_skb(NLMSG_SPACE(payload_len), GFP_KERNEL); | ||
58 | if (!skb) { | ||
59 | rc = -ENOMEM; | ||
60 | ecryptfs_printk(KERN_ERR, "Failed to allocate socket buffer\n"); | ||
61 | goto out; | ||
62 | } | ||
63 | nlh = NLMSG_PUT(skb, daemon_pid, msg_ctx ? msg_ctx->counter : 0, | ||
64 | msg_type, payload_len); | ||
65 | nlh->nlmsg_flags = msg_flags; | ||
66 | if (msg_ctx && payload_len) { | ||
67 | msg = (struct ecryptfs_message *)NLMSG_DATA(nlh); | ||
68 | msg->index = msg_ctx->index; | ||
69 | msg->data_len = data_len; | ||
70 | memcpy(msg->data, data, data_len); | ||
71 | } | ||
72 | rc = netlink_unicast(ecryptfs_nl_sock, skb, daemon_pid, 0); | ||
73 | if (rc < 0) { | ||
74 | ecryptfs_printk(KERN_ERR, "Failed to send eCryptfs netlink " | ||
75 | "message; rc = [%d]\n", rc); | ||
76 | goto out; | ||
77 | } | ||
78 | rc = 0; | ||
79 | goto out; | ||
80 | nlmsg_failure: | ||
81 | rc = -EMSGSIZE; | ||
82 | kfree_skb(skb); | ||
83 | out: | ||
84 | return rc; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * ecryptfs_process_nl_reponse | ||
89 | * @skb: The socket buffer containing the netlink message of state | ||
90 | * RESPONSE | ||
91 | * | ||
92 | * Processes a response message after sending a operation request to | ||
93 | * userspace. Attempts to assign the msg to a netlink context element | ||
94 | * at the index specified in the msg. The sk_buff and nlmsghdr must | ||
95 | * be validated before this function. Returns zero upon delivery to | ||
96 | * desired context element; non-zero upon delivery failure or error. | ||
97 | */ | ||
98 | static int ecryptfs_process_nl_response(struct sk_buff *skb) | ||
99 | { | ||
100 | struct nlmsghdr *nlh = (struct nlmsghdr*)skb->data; | ||
101 | struct ecryptfs_message *msg = NLMSG_DATA(nlh); | ||
102 | int rc; | ||
103 | |||
104 | if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) { | ||
105 | rc = -EINVAL; | ||
106 | ecryptfs_printk(KERN_ERR, "Received netlink message with " | ||
107 | "incorrectly specified data length\n"); | ||
108 | goto out; | ||
109 | } | ||
110 | rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid, | ||
111 | NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq); | ||
112 | if (rc) | ||
113 | printk(KERN_ERR | ||
114 | "Error processing response message; rc = [%d]\n", rc); | ||
115 | out: | ||
116 | return rc; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * ecryptfs_process_nl_helo | ||
121 | * @skb: The socket buffer containing the nlmsghdr in HELO state | ||
122 | * | ||
123 | * Gets uid and pid of the skb and adds the values to the daemon id | ||
124 | * hash. Returns zero after adding a new daemon id to the hash list; | ||
125 | * non-zero otherwise. | ||
126 | */ | ||
127 | static int ecryptfs_process_nl_helo(struct sk_buff *skb) | ||
128 | { | ||
129 | int rc; | ||
130 | |||
131 | rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK, | ||
132 | NETLINK_CREDS(skb)->uid, | ||
133 | NETLINK_CREDS(skb)->pid); | ||
134 | if (rc) | ||
135 | printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc); | ||
136 | return rc; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * ecryptfs_process_nl_quit | ||
141 | * @skb: The socket buffer containing the nlmsghdr in QUIT state | ||
142 | * | ||
143 | * Gets uid and pid of the skb and deletes the corresponding daemon | ||
144 | * id, if it is the registered that is requesting the | ||
145 | * deletion. Returns zero after deleting the desired daemon id; | ||
146 | * non-zero otherwise. | ||
147 | */ | ||
148 | static int ecryptfs_process_nl_quit(struct sk_buff *skb) | ||
149 | { | ||
150 | int rc; | ||
151 | |||
152 | rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid, | ||
153 | NETLINK_CREDS(skb)->pid); | ||
154 | if (rc) | ||
155 | printk(KERN_WARNING | ||
156 | "Error processing QUIT message; rc = [%d]\n", rc); | ||
157 | return rc; | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * ecryptfs_receive_nl_message | ||
162 | * | ||
163 | * Callback function called by netlink system when a message arrives. | ||
164 | * If the message looks to be valid, then an attempt is made to assign | ||
165 | * it to its desired netlink context element and wake up the process | ||
166 | * that is waiting for a response. | ||
167 | */ | ||
168 | static void ecryptfs_receive_nl_message(struct sock *sk, int len) | ||
169 | { | ||
170 | struct sk_buff *skb; | ||
171 | struct nlmsghdr *nlh; | ||
172 | int rc = 0; /* skb_recv_datagram requires this */ | ||
173 | |||
174 | receive: | ||
175 | skb = skb_recv_datagram(sk, 0, 0, &rc); | ||
176 | if (rc == -EINTR) | ||
177 | goto receive; | ||
178 | else if (rc < 0) { | ||
179 | ecryptfs_printk(KERN_ERR, "Error occurred while " | ||
180 | "receiving eCryptfs netlink message; " | ||
181 | "rc = [%d]\n", rc); | ||
182 | return; | ||
183 | } | ||
184 | nlh = (struct nlmsghdr *)skb->data; | ||
185 | if (!NLMSG_OK(nlh, skb->len)) { | ||
186 | ecryptfs_printk(KERN_ERR, "Received corrupt netlink " | ||
187 | "message\n"); | ||
188 | goto free; | ||
189 | } | ||
190 | switch (nlh->nlmsg_type) { | ||
191 | case ECRYPTFS_NLMSG_RESPONSE: | ||
192 | if (ecryptfs_process_nl_response(skb)) { | ||
193 | ecryptfs_printk(KERN_WARNING, "Failed to " | ||
194 | "deliver netlink response to " | ||
195 | "requesting operation\n"); | ||
196 | } | ||
197 | break; | ||
198 | case ECRYPTFS_NLMSG_HELO: | ||
199 | if (ecryptfs_process_nl_helo(skb)) { | ||
200 | ecryptfs_printk(KERN_WARNING, "Failed to " | ||
201 | "fulfill HELO request\n"); | ||
202 | } | ||
203 | break; | ||
204 | case ECRYPTFS_NLMSG_QUIT: | ||
205 | if (ecryptfs_process_nl_quit(skb)) { | ||
206 | ecryptfs_printk(KERN_WARNING, "Failed to " | ||
207 | "fulfill QUIT request\n"); | ||
208 | } | ||
209 | break; | ||
210 | default: | ||
211 | ecryptfs_printk(KERN_WARNING, "Dropping netlink " | ||
212 | "message of unrecognized type [%d]\n", | ||
213 | nlh->nlmsg_type); | ||
214 | break; | ||
215 | } | ||
216 | free: | ||
217 | kfree_skb(skb); | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * ecryptfs_init_netlink | ||
222 | * | ||
223 | * Initializes the daemon id hash list, netlink context array, and | ||
224 | * necessary locks. Returns zero upon success; non-zero upon error. | ||
225 | */ | ||
226 | int ecryptfs_init_netlink(void) | ||
227 | { | ||
228 | int rc; | ||
229 | |||
230 | ecryptfs_nl_sock = netlink_kernel_create(NETLINK_ECRYPTFS, 0, | ||
231 | ecryptfs_receive_nl_message, | ||
232 | THIS_MODULE); | ||
233 | if (!ecryptfs_nl_sock) { | ||
234 | rc = -EIO; | ||
235 | ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n"); | ||
236 | goto out; | ||
237 | } | ||
238 | ecryptfs_nl_sock->sk_sndtimeo = ECRYPTFS_DEFAULT_SEND_TIMEOUT; | ||
239 | rc = 0; | ||
240 | out: | ||
241 | return rc; | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * ecryptfs_release_netlink | ||
246 | * | ||
247 | * Frees all memory used by the netlink context array and releases the | ||
248 | * netlink socket. | ||
249 | */ | ||
250 | void ecryptfs_release_netlink(void) | ||
251 | { | ||
252 | if (ecryptfs_nl_sock && ecryptfs_nl_sock->sk_socket) | ||
253 | sock_release(ecryptfs_nl_sock->sk_socket); | ||
254 | ecryptfs_nl_sock = NULL; | ||
255 | } | ||
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index eaa5daaf106e..7b3f0cc09a6f 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
@@ -168,7 +168,7 @@ out: | |||
168 | return rc; | 168 | return rc; |
169 | } | 169 | } |
170 | 170 | ||
171 | struct super_operations ecryptfs_sops = { | 171 | const struct super_operations ecryptfs_sops = { |
172 | .alloc_inode = ecryptfs_alloc_inode, | 172 | .alloc_inode = ecryptfs_alloc_inode, |
173 | .destroy_inode = ecryptfs_destroy_inode, | 173 | .destroy_inode = ecryptfs_destroy_inode, |
174 | .drop_inode = generic_delete_inode, | 174 | .drop_inode = generic_delete_inode, |
diff --git a/fs/efs/dir.c b/fs/efs/dir.c index b46c488eefc8..dfb5cb400217 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c | |||
@@ -15,7 +15,7 @@ const struct file_operations efs_dir_operations = { | |||
15 | .readdir = efs_readdir, | 15 | .readdir = efs_readdir, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | struct inode_operations efs_dir_inode_operations = { | 18 | const struct inode_operations efs_dir_inode_operations = { |
19 | .lookup = efs_lookup, | 19 | .lookup = efs_lookup, |
20 | }; | 20 | }; |
21 | 21 | ||
diff --git a/fs/efs/super.c b/fs/efs/super.c index dfebf21289f4..c2235e46edcd 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c | |||
@@ -105,7 +105,7 @@ static int efs_remount(struct super_block *sb, int *flags, char *data) | |||
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
107 | 107 | ||
108 | static struct super_operations efs_superblock_operations = { | 108 | static const struct super_operations efs_superblock_operations = { |
109 | .alloc_inode = efs_alloc_inode, | 109 | .alloc_inode = efs_alloc_inode, |
110 | .destroy_inode = efs_destroy_inode, | 110 | .destroy_inode = efs_destroy_inode, |
111 | .read_inode = efs_read_inode, | 111 | .read_inode = efs_read_inode, |
@@ -405,12 +405,10 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
405 | bprm->loader += stack_base; | 405 | bprm->loader += stack_base; |
406 | bprm->exec += stack_base; | 406 | bprm->exec += stack_base; |
407 | 407 | ||
408 | mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); | 408 | mpnt = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
409 | if (!mpnt) | 409 | if (!mpnt) |
410 | return -ENOMEM; | 410 | return -ENOMEM; |
411 | 411 | ||
412 | memset(mpnt, 0, sizeof(*mpnt)); | ||
413 | |||
414 | down_write(&mm->mmap_sem); | 412 | down_write(&mm->mmap_sem); |
415 | { | 413 | { |
416 | mpnt->vm_mm = mm; | 414 | mpnt->vm_mm = mm; |
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index b1981d0e95ad..baf71dd721fa 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c | |||
@@ -29,7 +29,7 @@ | |||
29 | * The file system contains group descriptors which are located after the | 29 | * The file system contains group descriptors which are located after the |
30 | * super block. Each descriptor contains the number of the bitmap block and | 30 | * super block. Each descriptor contains the number of the bitmap block and |
31 | * the free blocks count in the block. The descriptors are loaded in memory | 31 | * the free blocks count in the block. The descriptors are loaded in memory |
32 | * when a file system is mounted (see ext2_read_super). | 32 | * when a file system is mounted (see ext2_fill_super). |
33 | */ | 33 | */ |
34 | 34 | ||
35 | 35 | ||
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 0b02ba9642d2..e89bfc8cf957 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -368,6 +368,14 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir, | |||
368 | } | 368 | } |
369 | if (++n >= npages) | 369 | if (++n >= npages) |
370 | n = 0; | 370 | n = 0; |
371 | /* next page is past the blocks we've got */ | ||
372 | if (unlikely(n > (dir->i_blocks >> (PAGE_CACHE_SHIFT - 9)))) { | ||
373 | ext2_error(dir->i_sb, __FUNCTION__, | ||
374 | "dir %lu size %lld exceeds block count %llu", | ||
375 | dir->i_ino, dir->i_size, | ||
376 | (unsigned long long)dir->i_blocks); | ||
377 | goto out; | ||
378 | } | ||
371 | } while (n != start); | 379 | } while (n != start); |
372 | out: | 380 | out: |
373 | return NULL; | 381 | return NULL; |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index c19ac153f56b..e2a0ea50af1d 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
@@ -158,7 +158,7 @@ extern void ext2_write_super (struct super_block *); | |||
158 | extern const struct file_operations ext2_dir_operations; | 158 | extern const struct file_operations ext2_dir_operations; |
159 | 159 | ||
160 | /* file.c */ | 160 | /* file.c */ |
161 | extern struct inode_operations ext2_file_inode_operations; | 161 | extern const struct inode_operations ext2_file_inode_operations; |
162 | extern const struct file_operations ext2_file_operations; | 162 | extern const struct file_operations ext2_file_operations; |
163 | extern const struct file_operations ext2_xip_file_operations; | 163 | extern const struct file_operations ext2_xip_file_operations; |
164 | 164 | ||
@@ -168,9 +168,9 @@ extern const struct address_space_operations ext2_aops_xip; | |||
168 | extern const struct address_space_operations ext2_nobh_aops; | 168 | extern const struct address_space_operations ext2_nobh_aops; |
169 | 169 | ||
170 | /* namei.c */ | 170 | /* namei.c */ |
171 | extern struct inode_operations ext2_dir_inode_operations; | 171 | extern const struct inode_operations ext2_dir_inode_operations; |
172 | extern struct inode_operations ext2_special_inode_operations; | 172 | extern const struct inode_operations ext2_special_inode_operations; |
173 | 173 | ||
174 | /* symlink.c */ | 174 | /* symlink.c */ |
175 | extern struct inode_operations ext2_fast_symlink_inode_operations; | 175 | extern const struct inode_operations ext2_fast_symlink_inode_operations; |
176 | extern struct inode_operations ext2_symlink_inode_operations; | 176 | extern const struct inode_operations ext2_symlink_inode_operations; |
diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 2dba473c524a..566d4e2d3852 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c | |||
@@ -75,7 +75,7 @@ const struct file_operations ext2_xip_file_operations = { | |||
75 | }; | 75 | }; |
76 | #endif | 76 | #endif |
77 | 77 | ||
78 | struct inode_operations ext2_file_inode_operations = { | 78 | const struct inode_operations ext2_file_inode_operations = { |
79 | .truncate = ext2_truncate, | 79 | .truncate = ext2_truncate, |
80 | #ifdef CONFIG_EXT2_FS_XATTR | 80 | #ifdef CONFIG_EXT2_FS_XATTR |
81 | .setxattr = generic_setxattr, | 81 | .setxattr = generic_setxattr, |
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index e1af5b4cf80c..e69beed839ac 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c | |||
@@ -373,7 +373,7 @@ out: | |||
373 | return err; | 373 | return err; |
374 | } | 374 | } |
375 | 375 | ||
376 | struct inode_operations ext2_dir_inode_operations = { | 376 | const struct inode_operations ext2_dir_inode_operations = { |
377 | .create = ext2_create, | 377 | .create = ext2_create, |
378 | .lookup = ext2_lookup, | 378 | .lookup = ext2_lookup, |
379 | .link = ext2_link, | 379 | .link = ext2_link, |
@@ -393,7 +393,7 @@ struct inode_operations ext2_dir_inode_operations = { | |||
393 | .permission = ext2_permission, | 393 | .permission = ext2_permission, |
394 | }; | 394 | }; |
395 | 395 | ||
396 | struct inode_operations ext2_special_inode_operations = { | 396 | const struct inode_operations ext2_special_inode_operations = { |
397 | #ifdef CONFIG_EXT2_FS_XATTR | 397 | #ifdef CONFIG_EXT2_FS_XATTR |
398 | .setxattr = generic_setxattr, | 398 | .setxattr = generic_setxattr, |
399 | .getxattr = generic_getxattr, | 399 | .getxattr = generic_getxattr, |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 6347c2dbdd81..a046a419d8af 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -231,7 +231,7 @@ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, siz | |||
231 | static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); | 231 | static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); |
232 | #endif | 232 | #endif |
233 | 233 | ||
234 | static struct super_operations ext2_sops = { | 234 | static const struct super_operations ext2_sops = { |
235 | .alloc_inode = ext2_alloc_inode, | 235 | .alloc_inode = ext2_alloc_inode, |
236 | .destroy_inode = ext2_destroy_inode, | 236 | .destroy_inode = ext2_destroy_inode, |
237 | .read_inode = ext2_read_inode, | 237 | .read_inode = ext2_read_inode, |
@@ -708,10 +708,14 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
708 | set_opt(sbi->s_mount_opt, GRPID); | 708 | set_opt(sbi->s_mount_opt, GRPID); |
709 | if (def_mount_opts & EXT2_DEFM_UID16) | 709 | if (def_mount_opts & EXT2_DEFM_UID16) |
710 | set_opt(sbi->s_mount_opt, NO_UID32); | 710 | set_opt(sbi->s_mount_opt, NO_UID32); |
711 | #ifdef CONFIG_EXT2_FS_XATTR | ||
711 | if (def_mount_opts & EXT2_DEFM_XATTR_USER) | 712 | if (def_mount_opts & EXT2_DEFM_XATTR_USER) |
712 | set_opt(sbi->s_mount_opt, XATTR_USER); | 713 | set_opt(sbi->s_mount_opt, XATTR_USER); |
714 | #endif | ||
715 | #ifdef CONFIG_EXT2_FS_POSIX_ACL | ||
713 | if (def_mount_opts & EXT2_DEFM_ACL) | 716 | if (def_mount_opts & EXT2_DEFM_ACL) |
714 | set_opt(sbi->s_mount_opt, POSIX_ACL); | 717 | set_opt(sbi->s_mount_opt, POSIX_ACL); |
718 | #endif | ||
715 | 719 | ||
716 | if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC) | 720 | if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC) |
717 | set_opt(sbi->s_mount_opt, ERRORS_PANIC); | 721 | set_opt(sbi->s_mount_opt, ERRORS_PANIC); |
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index 1e67d87cfa91..4e2426e22bbe 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c | |||
@@ -28,7 +28,7 @@ static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
28 | return NULL; | 28 | return NULL; |
29 | } | 29 | } |
30 | 30 | ||
31 | struct inode_operations ext2_symlink_inode_operations = { | 31 | const struct inode_operations ext2_symlink_inode_operations = { |
32 | .readlink = generic_readlink, | 32 | .readlink = generic_readlink, |
33 | .follow_link = page_follow_link_light, | 33 | .follow_link = page_follow_link_light, |
34 | .put_link = page_put_link, | 34 | .put_link = page_put_link, |
@@ -40,7 +40,7 @@ struct inode_operations ext2_symlink_inode_operations = { | |||
40 | #endif | 40 | #endif |
41 | }; | 41 | }; |
42 | 42 | ||
43 | struct inode_operations ext2_fast_symlink_inode_operations = { | 43 | const struct inode_operations ext2_fast_symlink_inode_operations = { |
44 | .readlink = generic_readlink, | 44 | .readlink = generic_readlink, |
45 | .follow_link = ext2_follow_link, | 45 | .follow_link = ext2_follow_link, |
46 | #ifdef CONFIG_EXT2_FS_XATTR | 46 | #ifdef CONFIG_EXT2_FS_XATTR |
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 22161740ba29..ca8aee6efe37 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -32,7 +32,7 @@ | |||
32 | * The file system contains group descriptors which are located after the | 32 | * The file system contains group descriptors which are located after the |
33 | * super block. Each descriptor contains the number of the bitmap block and | 33 | * super block. Each descriptor contains the number of the bitmap block and |
34 | * the free blocks count in the block. The descriptors are loaded in memory | 34 | * the free blocks count in the block. The descriptors are loaded in memory |
35 | * when a file system is mounted (see ext3_read_super). | 35 | * when a file system is mounted (see ext3_fill_super). |
36 | */ | 36 | */ |
37 | 37 | ||
38 | 38 | ||
diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 881f6365c41a..1e6f13864536 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c | |||
@@ -125,7 +125,7 @@ const struct file_operations ext3_file_operations = { | |||
125 | .splice_write = generic_file_splice_write, | 125 | .splice_write = generic_file_splice_write, |
126 | }; | 126 | }; |
127 | 127 | ||
128 | struct inode_operations ext3_file_inode_operations = { | 128 | const struct inode_operations ext3_file_inode_operations = { |
129 | .truncate = ext3_truncate, | 129 | .truncate = ext3_truncate, |
130 | .setattr = ext3_setattr, | 130 | .setattr = ext3_setattr, |
131 | #ifdef CONFIG_EXT3_FS_XATTR | 131 | #ifdef CONFIG_EXT3_FS_XATTR |
diff --git a/fs/ext3/hash.c b/fs/ext3/hash.c index deeb27b5ba83..c30e149fbd2e 100644 --- a/fs/ext3/hash.c +++ b/fs/ext3/hash.c | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/jbd.h> | 13 | #include <linux/jbd.h> |
14 | #include <linux/sched.h> | ||
15 | #include <linux/ext3_fs.h> | 14 | #include <linux/ext3_fs.h> |
16 | #include <linux/cryptohash.h> | 15 | #include <linux/cryptohash.h> |
17 | 16 | ||
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index beaf25f5112f..8a824f4ce5c6 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -947,7 +947,7 @@ out: | |||
947 | static int ext3_get_block(struct inode *inode, sector_t iblock, | 947 | static int ext3_get_block(struct inode *inode, sector_t iblock, |
948 | struct buffer_head *bh_result, int create) | 948 | struct buffer_head *bh_result, int create) |
949 | { | 949 | { |
950 | handle_t *handle = journal_current_handle(); | 950 | handle_t *handle = ext3_journal_current_handle(); |
951 | int ret = 0; | 951 | int ret = 0; |
952 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; | 952 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; |
953 | 953 | ||
@@ -1717,7 +1717,7 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, | |||
1717 | /* | 1717 | /* |
1718 | * Reacquire the handle: ext3_get_block() can restart the transaction | 1718 | * Reacquire the handle: ext3_get_block() can restart the transaction |
1719 | */ | 1719 | */ |
1720 | handle = journal_current_handle(); | 1720 | handle = ext3_journal_current_handle(); |
1721 | 1721 | ||
1722 | out_stop: | 1722 | out_stop: |
1723 | if (handle) { | 1723 | if (handle) { |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 4df39c4315e1..49159f13cc1f 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -1618,21 +1618,6 @@ static int ext3_delete_entry (handle_t *handle, | |||
1618 | return -ENOENT; | 1618 | return -ENOENT; |
1619 | } | 1619 | } |
1620 | 1620 | ||
1621 | /* | ||
1622 | * ext3_mark_inode_dirty is somewhat expensive, so unlike ext2 we | ||
1623 | * do not perform it in these functions. We perform it at the call site, | ||
1624 | * if it is needed. | ||
1625 | */ | ||
1626 | static inline void ext3_inc_count(handle_t *handle, struct inode *inode) | ||
1627 | { | ||
1628 | inc_nlink(inode); | ||
1629 | } | ||
1630 | |||
1631 | static inline void ext3_dec_count(handle_t *handle, struct inode *inode) | ||
1632 | { | ||
1633 | drop_nlink(inode); | ||
1634 | } | ||
1635 | |||
1636 | static int ext3_add_nondir(handle_t *handle, | 1621 | static int ext3_add_nondir(handle_t *handle, |
1637 | struct dentry *dentry, struct inode *inode) | 1622 | struct dentry *dentry, struct inode *inode) |
1638 | { | 1623 | { |
@@ -1642,7 +1627,7 @@ static int ext3_add_nondir(handle_t *handle, | |||
1642 | d_instantiate(dentry, inode); | 1627 | d_instantiate(dentry, inode); |
1643 | return 0; | 1628 | return 0; |
1644 | } | 1629 | } |
1645 | ext3_dec_count(handle, inode); | 1630 | drop_nlink(inode); |
1646 | iput(inode); | 1631 | iput(inode); |
1647 | return err; | 1632 | return err; |
1648 | } | 1633 | } |
@@ -2163,7 +2148,7 @@ retry: | |||
2163 | err = __page_symlink(inode, symname, l, | 2148 | err = __page_symlink(inode, symname, l, |
2164 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | 2149 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); |
2165 | if (err) { | 2150 | if (err) { |
2166 | ext3_dec_count(handle, inode); | 2151 | drop_nlink(inode); |
2167 | ext3_mark_inode_dirty(handle, inode); | 2152 | ext3_mark_inode_dirty(handle, inode); |
2168 | iput (inode); | 2153 | iput (inode); |
2169 | goto out_stop; | 2154 | goto out_stop; |
@@ -2191,6 +2176,12 @@ static int ext3_link (struct dentry * old_dentry, | |||
2191 | 2176 | ||
2192 | if (inode->i_nlink >= EXT3_LINK_MAX) | 2177 | if (inode->i_nlink >= EXT3_LINK_MAX) |
2193 | return -EMLINK; | 2178 | return -EMLINK; |
2179 | /* | ||
2180 | * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing | ||
2181 | * otherwise has the potential to corrupt the orphan inode list. | ||
2182 | */ | ||
2183 | if (inode->i_nlink == 0) | ||
2184 | return -ENOENT; | ||
2194 | 2185 | ||
2195 | retry: | 2186 | retry: |
2196 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + | 2187 | handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + |
@@ -2202,7 +2193,7 @@ retry: | |||
2202 | handle->h_sync = 1; | 2193 | handle->h_sync = 1; |
2203 | 2194 | ||
2204 | inode->i_ctime = CURRENT_TIME_SEC; | 2195 | inode->i_ctime = CURRENT_TIME_SEC; |
2205 | ext3_inc_count(handle, inode); | 2196 | inc_nlink(inode); |
2206 | atomic_inc(&inode->i_count); | 2197 | atomic_inc(&inode->i_count); |
2207 | 2198 | ||
2208 | err = ext3_add_nondir(handle, dentry, inode); | 2199 | err = ext3_add_nondir(handle, dentry, inode); |
@@ -2374,7 +2365,7 @@ end_rename: | |||
2374 | /* | 2365 | /* |
2375 | * directories can handle most operations... | 2366 | * directories can handle most operations... |
2376 | */ | 2367 | */ |
2377 | struct inode_operations ext3_dir_inode_operations = { | 2368 | const struct inode_operations ext3_dir_inode_operations = { |
2378 | .create = ext3_create, | 2369 | .create = ext3_create, |
2379 | .lookup = ext3_lookup, | 2370 | .lookup = ext3_lookup, |
2380 | .link = ext3_link, | 2371 | .link = ext3_link, |
@@ -2394,7 +2385,7 @@ struct inode_operations ext3_dir_inode_operations = { | |||
2394 | .permission = ext3_permission, | 2385 | .permission = ext3_permission, |
2395 | }; | 2386 | }; |
2396 | 2387 | ||
2397 | struct inode_operations ext3_special_inode_operations = { | 2388 | const struct inode_operations ext3_special_inode_operations = { |
2398 | .setattr = ext3_setattr, | 2389 | .setattr = ext3_setattr, |
2399 | #ifdef CONFIG_EXT3_FS_XATTR | 2390 | #ifdef CONFIG_EXT3_FS_XATTR |
2400 | .setxattr = generic_setxattr, | 2391 | .setxattr = generic_setxattr, |
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index b73cba12f79c..ecf89904c113 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | #define EXT3FS_DEBUG | 12 | #define EXT3FS_DEBUG |
13 | 13 | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
16 | #include <linux/ext3_jbd.h> | 15 | #include <linux/ext3_jbd.h> |
17 | 16 | ||
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index b34886734a44..4a4fcd6868c7 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -639,7 +639,7 @@ static struct quotactl_ops ext3_qctl_operations = { | |||
639 | }; | 639 | }; |
640 | #endif | 640 | #endif |
641 | 641 | ||
642 | static struct super_operations ext3_sops = { | 642 | static const struct super_operations ext3_sops = { |
643 | .alloc_inode = ext3_alloc_inode, | 643 | .alloc_inode = ext3_alloc_inode, |
644 | .destroy_inode = ext3_destroy_inode, | 644 | .destroy_inode = ext3_destroy_inode, |
645 | .read_inode = ext3_read_inode, | 645 | .read_inode = ext3_read_inode, |
@@ -1459,10 +1459,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1459 | set_opt(sbi->s_mount_opt, GRPID); | 1459 | set_opt(sbi->s_mount_opt, GRPID); |
1460 | if (def_mount_opts & EXT3_DEFM_UID16) | 1460 | if (def_mount_opts & EXT3_DEFM_UID16) |
1461 | set_opt(sbi->s_mount_opt, NO_UID32); | 1461 | set_opt(sbi->s_mount_opt, NO_UID32); |
1462 | #ifdef CONFIG_EXT3_FS_XATTR | ||
1462 | if (def_mount_opts & EXT3_DEFM_XATTR_USER) | 1463 | if (def_mount_opts & EXT3_DEFM_XATTR_USER) |
1463 | set_opt(sbi->s_mount_opt, XATTR_USER); | 1464 | set_opt(sbi->s_mount_opt, XATTR_USER); |
1465 | #endif | ||
1466 | #ifdef CONFIG_EXT3_FS_POSIX_ACL | ||
1464 | if (def_mount_opts & EXT3_DEFM_ACL) | 1467 | if (def_mount_opts & EXT3_DEFM_ACL) |
1465 | set_opt(sbi->s_mount_opt, POSIX_ACL); | 1468 | set_opt(sbi->s_mount_opt, POSIX_ACL); |
1469 | #endif | ||
1466 | if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_DATA) | 1470 | if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_DATA) |
1467 | sbi->s_mount_opt |= EXT3_MOUNT_JOURNAL_DATA; | 1471 | sbi->s_mount_opt |= EXT3_MOUNT_JOURNAL_DATA; |
1468 | else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_ORDERED) | 1472 | else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_ORDERED) |
@@ -2344,6 +2348,22 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2344 | err = -EROFS; | 2348 | err = -EROFS; |
2345 | goto restore_opts; | 2349 | goto restore_opts; |
2346 | } | 2350 | } |
2351 | |||
2352 | /* | ||
2353 | * If we have an unprocessed orphan list hanging | ||
2354 | * around from a previously readonly bdev mount, | ||
2355 | * require a full umount/remount for now. | ||
2356 | */ | ||
2357 | if (es->s_last_orphan) { | ||
2358 | printk(KERN_WARNING "EXT3-fs: %s: couldn't " | ||
2359 | "remount RDWR because of unprocessed " | ||
2360 | "orphan inode list. Please " | ||
2361 | "umount/remount instead.\n", | ||
2362 | sb->s_id); | ||
2363 | err = -EINVAL; | ||
2364 | goto restore_opts; | ||
2365 | } | ||
2366 | |||
2347 | /* | 2367 | /* |
2348 | * Mounting a RDONLY partition read-write, so reread | 2368 | * Mounting a RDONLY partition read-write, so reread |
2349 | * and store the current valid flag. (It may have | 2369 | * and store the current valid flag. (It may have |
diff --git a/fs/ext3/symlink.c b/fs/ext3/symlink.c index 4f79122cde67..ff7b4ccd8983 100644 --- a/fs/ext3/symlink.c +++ b/fs/ext3/symlink.c | |||
@@ -30,7 +30,7 @@ static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
30 | return NULL; | 30 | return NULL; |
31 | } | 31 | } |
32 | 32 | ||
33 | struct inode_operations ext3_symlink_inode_operations = { | 33 | const struct inode_operations ext3_symlink_inode_operations = { |
34 | .readlink = generic_readlink, | 34 | .readlink = generic_readlink, |
35 | .follow_link = page_follow_link_light, | 35 | .follow_link = page_follow_link_light, |
36 | .put_link = page_put_link, | 36 | .put_link = page_put_link, |
@@ -42,7 +42,7 @@ struct inode_operations ext3_symlink_inode_operations = { | |||
42 | #endif | 42 | #endif |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct inode_operations ext3_fast_symlink_inode_operations = { | 45 | const struct inode_operations ext3_fast_symlink_inode_operations = { |
46 | .readlink = generic_readlink, | 46 | .readlink = generic_readlink, |
47 | .follow_link = ext3_follow_link, | 47 | .follow_link = ext3_follow_link, |
48 | #ifdef CONFIG_EXT3_FS_XATTR | 48 | #ifdef CONFIG_EXT3_FS_XATTR |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index c4dd1103ccf1..8a23483ca8d0 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -50,7 +50,7 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, | |||
50 | * The file system contains group descriptors which are located after the | 50 | * The file system contains group descriptors which are located after the |
51 | * super block. Each descriptor contains the number of the bitmap block and | 51 | * super block. Each descriptor contains the number of the bitmap block and |
52 | * the free blocks count in the block. The descriptors are loaded in memory | 52 | * the free blocks count in the block. The descriptors are loaded in memory |
53 | * when a file system is mounted (see ext4_read_super). | 53 | * when a file system is mounted (see ext4_fill_super). |
54 | */ | 54 | */ |
55 | 55 | ||
56 | 56 | ||
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index dc2724fa7622..7916b50f9a13 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -222,7 +222,7 @@ static int ext4_ext_space_block(struct inode *inode) | |||
222 | 222 | ||
223 | size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) | 223 | size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) |
224 | / sizeof(struct ext4_extent); | 224 | / sizeof(struct ext4_extent); |
225 | #ifdef AGRESSIVE_TEST | 225 | #ifdef AGGRESSIVE_TEST |
226 | if (size > 6) | 226 | if (size > 6) |
227 | size = 6; | 227 | size = 6; |
228 | #endif | 228 | #endif |
@@ -235,7 +235,7 @@ static int ext4_ext_space_block_idx(struct inode *inode) | |||
235 | 235 | ||
236 | size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) | 236 | size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) |
237 | / sizeof(struct ext4_extent_idx); | 237 | / sizeof(struct ext4_extent_idx); |
238 | #ifdef AGRESSIVE_TEST | 238 | #ifdef AGGRESSIVE_TEST |
239 | if (size > 5) | 239 | if (size > 5) |
240 | size = 5; | 240 | size = 5; |
241 | #endif | 241 | #endif |
@@ -249,7 +249,7 @@ static int ext4_ext_space_root(struct inode *inode) | |||
249 | size = sizeof(EXT4_I(inode)->i_data); | 249 | size = sizeof(EXT4_I(inode)->i_data); |
250 | size -= sizeof(struct ext4_extent_header); | 250 | size -= sizeof(struct ext4_extent_header); |
251 | size /= sizeof(struct ext4_extent); | 251 | size /= sizeof(struct ext4_extent); |
252 | #ifdef AGRESSIVE_TEST | 252 | #ifdef AGGRESSIVE_TEST |
253 | if (size > 3) | 253 | if (size > 3) |
254 | size = 3; | 254 | size = 3; |
255 | #endif | 255 | #endif |
@@ -263,7 +263,7 @@ static int ext4_ext_space_root_idx(struct inode *inode) | |||
263 | size = sizeof(EXT4_I(inode)->i_data); | 263 | size = sizeof(EXT4_I(inode)->i_data); |
264 | size -= sizeof(struct ext4_extent_header); | 264 | size -= sizeof(struct ext4_extent_header); |
265 | size /= sizeof(struct ext4_extent_idx); | 265 | size /= sizeof(struct ext4_extent_idx); |
266 | #ifdef AGRESSIVE_TEST | 266 | #ifdef AGGRESSIVE_TEST |
267 | if (size > 4) | 267 | if (size > 4) |
268 | size = 4; | 268 | size = 4; |
269 | #endif | 269 | #endif |
@@ -1118,7 +1118,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | |||
1118 | */ | 1118 | */ |
1119 | if (le16_to_cpu(ex1->ee_len) + le16_to_cpu(ex2->ee_len) > EXT_MAX_LEN) | 1119 | if (le16_to_cpu(ex1->ee_len) + le16_to_cpu(ex2->ee_len) > EXT_MAX_LEN) |
1120 | return 0; | 1120 | return 0; |
1121 | #ifdef AGRESSIVE_TEST | 1121 | #ifdef AGGRESSIVE_TEST |
1122 | if (le16_to_cpu(ex1->ee_len) >= 4) | 1122 | if (le16_to_cpu(ex1->ee_len) >= 4) |
1123 | return 0; | 1123 | return 0; |
1124 | #endif | 1124 | #endif |
@@ -1891,8 +1891,8 @@ void ext4_ext_init(struct super_block *sb) | |||
1891 | 1891 | ||
1892 | if (test_opt(sb, EXTENTS)) { | 1892 | if (test_opt(sb, EXTENTS)) { |
1893 | printk("EXT4-fs: file extents enabled"); | 1893 | printk("EXT4-fs: file extents enabled"); |
1894 | #ifdef AGRESSIVE_TEST | 1894 | #ifdef AGGRESSIVE_TEST |
1895 | printk(", agressive tests"); | 1895 | printk(", aggressive tests"); |
1896 | #endif | 1896 | #endif |
1897 | #ifdef CHECK_BINSEARCH | 1897 | #ifdef CHECK_BINSEARCH |
1898 | printk(", check binsearch"); | 1898 | printk(", check binsearch"); |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 3bbc24b58785..3c6c1fd2be90 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -125,7 +125,7 @@ const struct file_operations ext4_file_operations = { | |||
125 | .splice_write = generic_file_splice_write, | 125 | .splice_write = generic_file_splice_write, |
126 | }; | 126 | }; |
127 | 127 | ||
128 | struct inode_operations ext4_file_inode_operations = { | 128 | const struct inode_operations ext4_file_inode_operations = { |
129 | .truncate = ext4_truncate, | 129 | .truncate = ext4_truncate, |
130 | .setattr = ext4_setattr, | 130 | .setattr = ext4_setattr, |
131 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 131 | #ifdef CONFIG_EXT4DEV_FS_XATTR |
diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c index a67966385e06..1555024e3b36 100644 --- a/fs/ext4/hash.c +++ b/fs/ext4/hash.c | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/jbd2.h> | 13 | #include <linux/jbd2.h> |
14 | #include <linux/sched.h> | ||
15 | #include <linux/ext4_fs.h> | 14 | #include <linux/ext4_fs.h> |
16 | #include <linux/cryptohash.h> | 15 | #include <linux/cryptohash.h> |
17 | 16 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a127cc03c9fa..fbff4b9e122a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -946,7 +946,7 @@ out: | |||
946 | static int ext4_get_block(struct inode *inode, sector_t iblock, | 946 | static int ext4_get_block(struct inode *inode, sector_t iblock, |
947 | struct buffer_head *bh_result, int create) | 947 | struct buffer_head *bh_result, int create) |
948 | { | 948 | { |
949 | handle_t *handle = journal_current_handle(); | 949 | handle_t *handle = ext4_journal_current_handle(); |
950 | int ret = 0; | 950 | int ret = 0; |
951 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; | 951 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; |
952 | 952 | ||
@@ -1716,7 +1716,7 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, | |||
1716 | /* | 1716 | /* |
1717 | * Reacquire the handle: ext4_get_block() can restart the transaction | 1717 | * Reacquire the handle: ext4_get_block() can restart the transaction |
1718 | */ | 1718 | */ |
1719 | handle = journal_current_handle(); | 1719 | handle = ext4_journal_current_handle(); |
1720 | 1720 | ||
1721 | out_stop: | 1721 | out_stop: |
1722 | if (handle) { | 1722 | if (handle) { |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index e5a74a5ac261..e7e1d79a7d75 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1616,21 +1616,6 @@ static int ext4_delete_entry (handle_t *handle, | |||
1616 | return -ENOENT; | 1616 | return -ENOENT; |
1617 | } | 1617 | } |
1618 | 1618 | ||
1619 | /* | ||
1620 | * ext4_mark_inode_dirty is somewhat expensive, so unlike ext2 we | ||
1621 | * do not perform it in these functions. We perform it at the call site, | ||
1622 | * if it is needed. | ||
1623 | */ | ||
1624 | static inline void ext4_inc_count(handle_t *handle, struct inode *inode) | ||
1625 | { | ||
1626 | inc_nlink(inode); | ||
1627 | } | ||
1628 | |||
1629 | static inline void ext4_dec_count(handle_t *handle, struct inode *inode) | ||
1630 | { | ||
1631 | drop_nlink(inode); | ||
1632 | } | ||
1633 | |||
1634 | static int ext4_add_nondir(handle_t *handle, | 1619 | static int ext4_add_nondir(handle_t *handle, |
1635 | struct dentry *dentry, struct inode *inode) | 1620 | struct dentry *dentry, struct inode *inode) |
1636 | { | 1621 | { |
@@ -1640,7 +1625,7 @@ static int ext4_add_nondir(handle_t *handle, | |||
1640 | d_instantiate(dentry, inode); | 1625 | d_instantiate(dentry, inode); |
1641 | return 0; | 1626 | return 0; |
1642 | } | 1627 | } |
1643 | ext4_dec_count(handle, inode); | 1628 | drop_nlink(inode); |
1644 | iput(inode); | 1629 | iput(inode); |
1645 | return err; | 1630 | return err; |
1646 | } | 1631 | } |
@@ -2161,7 +2146,7 @@ retry: | |||
2161 | err = __page_symlink(inode, symname, l, | 2146 | err = __page_symlink(inode, symname, l, |
2162 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | 2147 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); |
2163 | if (err) { | 2148 | if (err) { |
2164 | ext4_dec_count(handle, inode); | 2149 | drop_nlink(inode); |
2165 | ext4_mark_inode_dirty(handle, inode); | 2150 | ext4_mark_inode_dirty(handle, inode); |
2166 | iput (inode); | 2151 | iput (inode); |
2167 | goto out_stop; | 2152 | goto out_stop; |
@@ -2189,6 +2174,12 @@ static int ext4_link (struct dentry * old_dentry, | |||
2189 | 2174 | ||
2190 | if (inode->i_nlink >= EXT4_LINK_MAX) | 2175 | if (inode->i_nlink >= EXT4_LINK_MAX) |
2191 | return -EMLINK; | 2176 | return -EMLINK; |
2177 | /* | ||
2178 | * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing | ||
2179 | * otherwise has the potential to corrupt the orphan inode list. | ||
2180 | */ | ||
2181 | if (inode->i_nlink == 0) | ||
2182 | return -ENOENT; | ||
2192 | 2183 | ||
2193 | retry: | 2184 | retry: |
2194 | handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + | 2185 | handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + |
@@ -2200,7 +2191,7 @@ retry: | |||
2200 | handle->h_sync = 1; | 2191 | handle->h_sync = 1; |
2201 | 2192 | ||
2202 | inode->i_ctime = CURRENT_TIME_SEC; | 2193 | inode->i_ctime = CURRENT_TIME_SEC; |
2203 | ext4_inc_count(handle, inode); | 2194 | inc_nlink(inode); |
2204 | atomic_inc(&inode->i_count); | 2195 | atomic_inc(&inode->i_count); |
2205 | 2196 | ||
2206 | err = ext4_add_nondir(handle, dentry, inode); | 2197 | err = ext4_add_nondir(handle, dentry, inode); |
@@ -2372,7 +2363,7 @@ end_rename: | |||
2372 | /* | 2363 | /* |
2373 | * directories can handle most operations... | 2364 | * directories can handle most operations... |
2374 | */ | 2365 | */ |
2375 | struct inode_operations ext4_dir_inode_operations = { | 2366 | const struct inode_operations ext4_dir_inode_operations = { |
2376 | .create = ext4_create, | 2367 | .create = ext4_create, |
2377 | .lookup = ext4_lookup, | 2368 | .lookup = ext4_lookup, |
2378 | .link = ext4_link, | 2369 | .link = ext4_link, |
@@ -2392,7 +2383,7 @@ struct inode_operations ext4_dir_inode_operations = { | |||
2392 | .permission = ext4_permission, | 2383 | .permission = ext4_permission, |
2393 | }; | 2384 | }; |
2394 | 2385 | ||
2395 | struct inode_operations ext4_special_inode_operations = { | 2386 | const struct inode_operations ext4_special_inode_operations = { |
2396 | .setattr = ext4_setattr, | 2387 | .setattr = ext4_setattr, |
2397 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 2388 | #ifdef CONFIG_EXT4DEV_FS_XATTR |
2398 | .setxattr = generic_setxattr, | 2389 | .setxattr = generic_setxattr, |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 4fe49c3661b2..ea99f6c97f56 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | #define EXT4FS_DEBUG | 12 | #define EXT4FS_DEBUG |
13 | 13 | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
16 | #include <linux/ext4_jbd2.h> | 15 | #include <linux/ext4_jbd2.h> |
17 | 16 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 486a641ca71b..61c4718e4a53 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -690,7 +690,7 @@ static struct quotactl_ops ext4_qctl_operations = { | |||
690 | }; | 690 | }; |
691 | #endif | 691 | #endif |
692 | 692 | ||
693 | static struct super_operations ext4_sops = { | 693 | static const struct super_operations ext4_sops = { |
694 | .alloc_inode = ext4_alloc_inode, | 694 | .alloc_inode = ext4_alloc_inode, |
695 | .destroy_inode = ext4_destroy_inode, | 695 | .destroy_inode = ext4_destroy_inode, |
696 | .read_inode = ext4_read_inode, | 696 | .read_inode = ext4_read_inode, |
@@ -1518,10 +1518,14 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1518 | set_opt(sbi->s_mount_opt, GRPID); | 1518 | set_opt(sbi->s_mount_opt, GRPID); |
1519 | if (def_mount_opts & EXT4_DEFM_UID16) | 1519 | if (def_mount_opts & EXT4_DEFM_UID16) |
1520 | set_opt(sbi->s_mount_opt, NO_UID32); | 1520 | set_opt(sbi->s_mount_opt, NO_UID32); |
1521 | #ifdef CONFIG_EXT4DEV_FS_XATTR | ||
1521 | if (def_mount_opts & EXT4_DEFM_XATTR_USER) | 1522 | if (def_mount_opts & EXT4_DEFM_XATTR_USER) |
1522 | set_opt(sbi->s_mount_opt, XATTR_USER); | 1523 | set_opt(sbi->s_mount_opt, XATTR_USER); |
1524 | #endif | ||
1525 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | ||
1523 | if (def_mount_opts & EXT4_DEFM_ACL) | 1526 | if (def_mount_opts & EXT4_DEFM_ACL) |
1524 | set_opt(sbi->s_mount_opt, POSIX_ACL); | 1527 | set_opt(sbi->s_mount_opt, POSIX_ACL); |
1528 | #endif | ||
1525 | if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) | 1529 | if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) |
1526 | sbi->s_mount_opt |= EXT4_MOUNT_JOURNAL_DATA; | 1530 | sbi->s_mount_opt |= EXT4_MOUNT_JOURNAL_DATA; |
1527 | else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED) | 1531 | else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED) |
@@ -2419,6 +2423,22 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data) | |||
2419 | err = -EROFS; | 2423 | err = -EROFS; |
2420 | goto restore_opts; | 2424 | goto restore_opts; |
2421 | } | 2425 | } |
2426 | |||
2427 | /* | ||
2428 | * If we have an unprocessed orphan list hanging | ||
2429 | * around from a previously readonly bdev mount, | ||
2430 | * require a full umount/remount for now. | ||
2431 | */ | ||
2432 | if (es->s_last_orphan) { | ||
2433 | printk(KERN_WARNING "EXT4-fs: %s: couldn't " | ||
2434 | "remount RDWR because of unprocessed " | ||
2435 | "orphan inode list. Please " | ||
2436 | "umount/remount instead.\n", | ||
2437 | sb->s_id); | ||
2438 | err = -EINVAL; | ||
2439 | goto restore_opts; | ||
2440 | } | ||
2441 | |||
2422 | /* | 2442 | /* |
2423 | * Mounting a RDONLY partition read-write, so reread | 2443 | * Mounting a RDONLY partition read-write, so reread |
2424 | * and store the current valid flag. (It may have | 2444 | * and store the current valid flag. (It may have |
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index fcf527286d75..e6f9da4287c4 100644 --- a/fs/ext4/symlink.c +++ b/fs/ext4/symlink.c | |||
@@ -30,7 +30,7 @@ static void * ext4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
30 | return NULL; | 30 | return NULL; |
31 | } | 31 | } |
32 | 32 | ||
33 | struct inode_operations ext4_symlink_inode_operations = { | 33 | const struct inode_operations ext4_symlink_inode_operations = { |
34 | .readlink = generic_readlink, | 34 | .readlink = generic_readlink, |
35 | .follow_link = page_follow_link_light, | 35 | .follow_link = page_follow_link_light, |
36 | .put_link = page_put_link, | 36 | .put_link = page_put_link, |
@@ -42,7 +42,7 @@ struct inode_operations ext4_symlink_inode_operations = { | |||
42 | #endif | 42 | #endif |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct inode_operations ext4_fast_symlink_inode_operations = { | 45 | const struct inode_operations ext4_fast_symlink_inode_operations = { |
46 | .readlink = generic_readlink, | 46 | .readlink = generic_readlink, |
47 | .follow_link = ext4_follow_link, | 47 | .follow_link = ext4_follow_link, |
48 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 48 | #ifdef CONFIG_EXT4DEV_FS_XATTR |
diff --git a/fs/fat/file.c b/fs/fat/file.c index c1237b70c1fe..55d3c7461c5b 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -312,7 +312,7 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
312 | } | 312 | } |
313 | EXPORT_SYMBOL_GPL(fat_getattr); | 313 | EXPORT_SYMBOL_GPL(fat_getattr); |
314 | 314 | ||
315 | struct inode_operations fat_file_inode_operations = { | 315 | const struct inode_operations fat_file_inode_operations = { |
316 | .truncate = fat_truncate, | 316 | .truncate = fat_truncate, |
317 | .setattr = fat_notify_change, | 317 | .setattr = fat_notify_change, |
318 | .getattr = fat_getattr, | 318 | .getattr = fat_getattr, |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index a9e4688582a2..9bfe607c892e 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -173,10 +173,12 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
173 | * | 173 | * |
174 | * But we must fill the remaining area or hole by nul for | 174 | * But we must fill the remaining area or hole by nul for |
175 | * updating ->mmu_private. | 175 | * updating ->mmu_private. |
176 | * | ||
177 | * Return 0, and fallback to normal buffered write. | ||
176 | */ | 178 | */ |
177 | loff_t size = offset + iov_length(iov, nr_segs); | 179 | loff_t size = offset + iov_length(iov, nr_segs); |
178 | if (MSDOS_I(inode)->mmu_private < size) | 180 | if (MSDOS_I(inode)->mmu_private < size) |
179 | return -EINVAL; | 181 | return 0; |
180 | } | 182 | } |
181 | 183 | ||
182 | /* | 184 | /* |
@@ -618,7 +620,7 @@ int fat_sync_inode(struct inode *inode) | |||
618 | EXPORT_SYMBOL_GPL(fat_sync_inode); | 620 | EXPORT_SYMBOL_GPL(fat_sync_inode); |
619 | 621 | ||
620 | static int fat_show_options(struct seq_file *m, struct vfsmount *mnt); | 622 | static int fat_show_options(struct seq_file *m, struct vfsmount *mnt); |
621 | static struct super_operations fat_sops = { | 623 | static const struct super_operations fat_sops = { |
622 | .alloc_inode = fat_alloc_inode, | 624 | .alloc_inode = fat_alloc_inode, |
623 | .destroy_inode = fat_destroy_inode, | 625 | .destroy_inode = fat_destroy_inode, |
624 | .write_inode = fat_write_inode, | 626 | .write_inode = fat_write_inode, |
@@ -1151,7 +1153,7 @@ static int fat_read_root(struct inode *inode) | |||
1151 | * Read the super block of an MS-DOS FS. | 1153 | * Read the super block of an MS-DOS FS. |
1152 | */ | 1154 | */ |
1153 | int fat_fill_super(struct super_block *sb, void *data, int silent, | 1155 | int fat_fill_super(struct super_block *sb, void *data, int silent, |
1154 | struct inode_operations *fs_dir_inode_ops, int isvfat) | 1156 | const struct inode_operations *fs_dir_inode_ops, int isvfat) |
1155 | { | 1157 | { |
1156 | struct inode *root_inode = NULL; | 1158 | struct inode *root_inode = NULL; |
1157 | struct buffer_head *bh; | 1159 | struct buffer_head *bh; |
diff --git a/fs/filesystems.c b/fs/filesystems.c index e3fa77c6ed56..7a4f61aa05f8 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/kmod.h> | 12 | #include <linux/kmod.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/sched.h> /* for 'current' */ | ||
16 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
17 | 16 | ||
18 | /* | 17 | /* |
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index 1cf1fe8466a2..91ccee8723f7 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h | |||
@@ -62,7 +62,7 @@ extern void vxfs_read_inode(struct inode *); | |||
62 | extern void vxfs_clear_inode(struct inode *); | 62 | extern void vxfs_clear_inode(struct inode *); |
63 | 63 | ||
64 | /* vxfs_lookup.c */ | 64 | /* vxfs_lookup.c */ |
65 | extern struct inode_operations vxfs_dir_inode_ops; | 65 | extern const struct inode_operations vxfs_dir_inode_ops; |
66 | extern const struct file_operations vxfs_dir_operations; | 66 | extern const struct file_operations vxfs_dir_operations; |
67 | 67 | ||
68 | /* vxfs_olt.c */ | 68 | /* vxfs_olt.c */ |
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c index 4e25f3fbed86..24b5a775ff96 100644 --- a/fs/freevxfs/vxfs_immed.c +++ b/fs/freevxfs/vxfs_immed.c | |||
@@ -48,7 +48,7 @@ static int vxfs_immed_readpage(struct file *, struct page *); | |||
48 | * Unliked all other operations we do not go through the pagecache, | 48 | * Unliked all other operations we do not go through the pagecache, |
49 | * but do all work directly on the inode. | 49 | * but do all work directly on the inode. |
50 | */ | 50 | */ |
51 | struct inode_operations vxfs_immed_symlink_iops = { | 51 | const struct inode_operations vxfs_immed_symlink_iops = { |
52 | .readlink = generic_readlink, | 52 | .readlink = generic_readlink, |
53 | .follow_link = vxfs_immed_follow_link, | 53 | .follow_link = vxfs_immed_follow_link, |
54 | }; | 54 | }; |
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 0b7ae897cb78..098a915fd9a1 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c | |||
@@ -44,7 +44,7 @@ | |||
44 | extern const struct address_space_operations vxfs_aops; | 44 | extern const struct address_space_operations vxfs_aops; |
45 | extern const struct address_space_operations vxfs_immed_aops; | 45 | extern const struct address_space_operations vxfs_immed_aops; |
46 | 46 | ||
47 | extern struct inode_operations vxfs_immed_symlink_iops; | 47 | extern const struct inode_operations vxfs_immed_symlink_iops; |
48 | 48 | ||
49 | struct kmem_cache *vxfs_inode_cachep; | 49 | struct kmem_cache *vxfs_inode_cachep; |
50 | 50 | ||
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 3995d7fbedab..bf86e5444ea6 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c | |||
@@ -52,7 +52,7 @@ | |||
52 | static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 52 | static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *); |
53 | static int vxfs_readdir(struct file *, void *, filldir_t); | 53 | static int vxfs_readdir(struct file *, void *, filldir_t); |
54 | 54 | ||
55 | struct inode_operations vxfs_dir_inode_ops = { | 55 | const struct inode_operations vxfs_dir_inode_ops = { |
56 | .lookup = vxfs_lookup, | 56 | .lookup = vxfs_lookup, |
57 | }; | 57 | }; |
58 | 58 | ||
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index ac28b0835ffc..647d600f0bc8 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c | |||
@@ -59,7 +59,7 @@ static void vxfs_put_super(struct super_block *); | |||
59 | static int vxfs_statfs(struct dentry *, struct kstatfs *); | 59 | static int vxfs_statfs(struct dentry *, struct kstatfs *); |
60 | static int vxfs_remount(struct super_block *, int *, char *); | 60 | static int vxfs_remount(struct super_block *, int *, char *); |
61 | 61 | ||
62 | static struct super_operations vxfs_super_ops = { | 62 | static const struct super_operations vxfs_super_ops = { |
63 | .read_inode = vxfs_read_inode, | 63 | .read_inode = vxfs_read_inode, |
64 | .clear_inode = vxfs_clear_inode, | 64 | .clear_inode = vxfs_clear_inode, |
65 | .put_super = vxfs_put_super, | 65 | .put_super = vxfs_put_super, |
diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 1794305f9ed8..105d4a271e07 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c | |||
@@ -73,7 +73,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent, | |||
73 | struct fuse_conn *fc, | 73 | struct fuse_conn *fc, |
74 | const char *name, | 74 | const char *name, |
75 | int mode, int nlink, | 75 | int mode, int nlink, |
76 | struct inode_operations *iop, | 76 | const struct inode_operations *iop, |
77 | const struct file_operations *fop) | 77 | const struct file_operations *fop) |
78 | { | 78 | { |
79 | struct dentry *dentry; | 79 | struct dentry *dentry; |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 40080477ceb4..406bf61ed510 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1242,7 +1242,7 @@ static int fuse_removexattr(struct dentry *entry, const char *name) | |||
1242 | return err; | 1242 | return err; |
1243 | } | 1243 | } |
1244 | 1244 | ||
1245 | static struct inode_operations fuse_dir_inode_operations = { | 1245 | static const struct inode_operations fuse_dir_inode_operations = { |
1246 | .lookup = fuse_lookup, | 1246 | .lookup = fuse_lookup, |
1247 | .mkdir = fuse_mkdir, | 1247 | .mkdir = fuse_mkdir, |
1248 | .symlink = fuse_symlink, | 1248 | .symlink = fuse_symlink, |
@@ -1270,7 +1270,7 @@ static const struct file_operations fuse_dir_operations = { | |||
1270 | .fsync = fuse_dir_fsync, | 1270 | .fsync = fuse_dir_fsync, |
1271 | }; | 1271 | }; |
1272 | 1272 | ||
1273 | static struct inode_operations fuse_common_inode_operations = { | 1273 | static const struct inode_operations fuse_common_inode_operations = { |
1274 | .setattr = fuse_setattr, | 1274 | .setattr = fuse_setattr, |
1275 | .permission = fuse_permission, | 1275 | .permission = fuse_permission, |
1276 | .getattr = fuse_getattr, | 1276 | .getattr = fuse_getattr, |
@@ -1280,7 +1280,7 @@ static struct inode_operations fuse_common_inode_operations = { | |||
1280 | .removexattr = fuse_removexattr, | 1280 | .removexattr = fuse_removexattr, |
1281 | }; | 1281 | }; |
1282 | 1282 | ||
1283 | static struct inode_operations fuse_symlink_inode_operations = { | 1283 | static const struct inode_operations fuse_symlink_inode_operations = { |
1284 | .setattr = fuse_setattr, | 1284 | .setattr = fuse_setattr, |
1285 | .follow_link = fuse_follow_link, | 1285 | .follow_link = fuse_follow_link, |
1286 | .put_link = fuse_put_link, | 1286 | .put_link = fuse_put_link, |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index f63efe1337ec..2fd06927e851 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -69,7 +69,7 @@ void fuse_finish_open(struct inode *inode, struct file *file, | |||
69 | if (outarg->open_flags & FOPEN_DIRECT_IO) | 69 | if (outarg->open_flags & FOPEN_DIRECT_IO) |
70 | file->f_op = &fuse_direct_io_file_operations; | 70 | file->f_op = &fuse_direct_io_file_operations; |
71 | if (!(outarg->open_flags & FOPEN_KEEP_CACHE)) | 71 | if (!(outarg->open_flags & FOPEN_KEEP_CACHE)) |
72 | invalidate_inode_pages(inode->i_mapping); | 72 | invalidate_mapping_pages(inode->i_mapping, 0, -1); |
73 | ff->fh = outarg->fh; | 73 | ff->fh = outarg->fh; |
74 | file->private_data = ff; | 74 | file->private_data = ff; |
75 | } | 75 | } |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 12450d2b320e..5ab8e50e7808 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -112,7 +112,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) | |||
112 | { | 112 | { |
113 | struct fuse_conn *fc = get_fuse_conn(inode); | 113 | struct fuse_conn *fc = get_fuse_conn(inode); |
114 | if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) | 114 | if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) |
115 | invalidate_inode_pages(inode->i_mapping); | 115 | invalidate_mapping_pages(inode->i_mapping, 0, -1); |
116 | 116 | ||
117 | inode->i_ino = attr->ino; | 117 | inode->i_ino = attr->ino; |
118 | inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777); | 118 | inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777); |
@@ -446,7 +446,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode) | |||
446 | return fuse_iget(sb, 1, 0, &attr); | 446 | return fuse_iget(sb, 1, 0, &attr); |
447 | } | 447 | } |
448 | 448 | ||
449 | static struct super_operations fuse_super_operations = { | 449 | static const struct super_operations fuse_super_operations = { |
450 | .alloc_inode = fuse_alloc_inode, | 450 | .alloc_inode = fuse_alloc_inode, |
451 | .destroy_inode = fuse_destroy_inode, | 451 | .destroy_inode = fuse_destroy_inode, |
452 | .read_inode = fuse_read_inode, | 452 | .read_inode = fuse_read_inode, |
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 113f6c9110c7..c53a5d2d0590 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index c93ca8f361b5..82a1ac7895a2 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -53,7 +53,6 @@ | |||
53 | * but never before the maximum hash table size has been reached. | 53 | * but never before the maximum hash table size has been reached. |
54 | */ | 54 | */ |
55 | 55 | ||
56 | #include <linux/sched.h> | ||
57 | #include <linux/slab.h> | 56 | #include <linux/slab.h> |
58 | #include <linux/spinlock.h> | 57 | #include <linux/spinlock.h> |
59 | #include <linux/buffer_head.h> | 58 | #include <linux/buffer_head.h> |
diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c index cd747c00f670..c1f44009853f 100644 --- a/fs/gfs2/eaops.c +++ b/fs/gfs2/eaops.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index 0c83c7f4dda8..5b83ca6acab1 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index c4b0391b7aa2..46af55355513 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/lm.c b/fs/gfs2/lm.c index e30673dd37e0..cfcc39b86a53 100644 --- a/fs/gfs2/lm.c +++ b/fs/gfs2/lm.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c index 3799f19b282f..1dd4215b83d0 100644 --- a/fs/gfs2/locking/dlm/plock.c +++ b/fs/gfs2/locking/dlm/plock.c | |||
@@ -264,7 +264,7 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) | |||
264 | return 0; | 264 | return 0; |
265 | } | 265 | } |
266 | 266 | ||
267 | static struct file_operations dev_fops = { | 267 | static const struct file_operations dev_fops = { |
268 | .read = dev_read, | 268 | .read = dev_read, |
269 | .write = dev_write, | 269 | .write = dev_write, |
270 | .poll = dev_poll, | 270 | .poll = dev_poll, |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 7c1a9e22a526..6e8a59809abf 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 0e34d9918973..e62d4f620c58 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -282,8 +282,7 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, | |||
282 | return; | 282 | return; |
283 | } | 283 | } |
284 | 284 | ||
285 | bd = kmem_cache_alloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL), | 285 | bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL), |
286 | memset(bd, 0, sizeof(struct gfs2_bufdata)); | ||
287 | bd->bd_bh = bh; | 286 | bd->bd_bh = bh; |
288 | bd->bd_gl = gl; | 287 | bd->bd_gl = gl; |
289 | 288 | ||
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index ef3092e29607..32caecd20300 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c index f2495f1e21ad..d9ecfd23a49e 100644 --- a/fs/gfs2/ondisk.c +++ b/fs/gfs2/ondisk.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c index 9187eb174b43..c6bac6b69420 100644 --- a/fs/gfs2/ops_dentry.c +++ b/fs/gfs2/ops_dentry.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index 4855e8cca622..1de05b63d43a 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index c996aa739a05..b50180e22779 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index f40a84807d75..d85f6e05cb95 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
@@ -1115,7 +1114,7 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name) | |||
1115 | return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er); | 1114 | return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er); |
1116 | } | 1115 | } |
1117 | 1116 | ||
1118 | struct inode_operations gfs2_file_iops = { | 1117 | const struct inode_operations gfs2_file_iops = { |
1119 | .permission = gfs2_permission, | 1118 | .permission = gfs2_permission, |
1120 | .setattr = gfs2_setattr, | 1119 | .setattr = gfs2_setattr, |
1121 | .getattr = gfs2_getattr, | 1120 | .getattr = gfs2_getattr, |
@@ -1125,7 +1124,7 @@ struct inode_operations gfs2_file_iops = { | |||
1125 | .removexattr = gfs2_removexattr, | 1124 | .removexattr = gfs2_removexattr, |
1126 | }; | 1125 | }; |
1127 | 1126 | ||
1128 | struct inode_operations gfs2_dev_iops = { | 1127 | const struct inode_operations gfs2_dev_iops = { |
1129 | .permission = gfs2_permission, | 1128 | .permission = gfs2_permission, |
1130 | .setattr = gfs2_setattr, | 1129 | .setattr = gfs2_setattr, |
1131 | .getattr = gfs2_getattr, | 1130 | .getattr = gfs2_getattr, |
@@ -1135,7 +1134,7 @@ struct inode_operations gfs2_dev_iops = { | |||
1135 | .removexattr = gfs2_removexattr, | 1134 | .removexattr = gfs2_removexattr, |
1136 | }; | 1135 | }; |
1137 | 1136 | ||
1138 | struct inode_operations gfs2_dir_iops = { | 1137 | const struct inode_operations gfs2_dir_iops = { |
1139 | .create = gfs2_create, | 1138 | .create = gfs2_create, |
1140 | .lookup = gfs2_lookup, | 1139 | .lookup = gfs2_lookup, |
1141 | .link = gfs2_link, | 1140 | .link = gfs2_link, |
@@ -1154,7 +1153,7 @@ struct inode_operations gfs2_dir_iops = { | |||
1154 | .removexattr = gfs2_removexattr, | 1153 | .removexattr = gfs2_removexattr, |
1155 | }; | 1154 | }; |
1156 | 1155 | ||
1157 | struct inode_operations gfs2_symlink_iops = { | 1156 | const struct inode_operations gfs2_symlink_iops = { |
1158 | .readlink = gfs2_readlink, | 1157 | .readlink = gfs2_readlink, |
1159 | .follow_link = gfs2_follow_link, | 1158 | .follow_link = gfs2_follow_link, |
1160 | .permission = gfs2_permission, | 1159 | .permission = gfs2_permission, |
diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h index b15acb4fd34c..34f0caac1a03 100644 --- a/fs/gfs2/ops_inode.h +++ b/fs/gfs2/ops_inode.h | |||
@@ -12,9 +12,9 @@ | |||
12 | 12 | ||
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | 14 | ||
15 | extern struct inode_operations gfs2_file_iops; | 15 | extern const struct inode_operations gfs2_file_iops; |
16 | extern struct inode_operations gfs2_dir_iops; | 16 | extern const struct inode_operations gfs2_dir_iops; |
17 | extern struct inode_operations gfs2_symlink_iops; | 17 | extern const struct inode_operations gfs2_symlink_iops; |
18 | extern struct inode_operations gfs2_dev_iops; | 18 | extern const struct inode_operations gfs2_dev_iops; |
19 | 19 | ||
20 | #endif /* __OPS_INODE_DOT_H__ */ | 20 | #endif /* __OPS_INODE_DOT_H__ */ |
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 47369d011214..b89999d3a767 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -468,7 +468,7 @@ static void gfs2_destroy_inode(struct inode *inode) | |||
468 | kmem_cache_free(gfs2_inode_cachep, inode); | 468 | kmem_cache_free(gfs2_inode_cachep, inode); |
469 | } | 469 | } |
470 | 470 | ||
471 | struct super_operations gfs2_super_ops = { | 471 | const struct super_operations gfs2_super_ops = { |
472 | .alloc_inode = gfs2_alloc_inode, | 472 | .alloc_inode = gfs2_alloc_inode, |
473 | .destroy_inode = gfs2_destroy_inode, | 473 | .destroy_inode = gfs2_destroy_inode, |
474 | .write_inode = gfs2_write_inode, | 474 | .write_inode = gfs2_write_inode, |
diff --git a/fs/gfs2/ops_super.h b/fs/gfs2/ops_super.h index 9de73f042f78..442a274c6272 100644 --- a/fs/gfs2/ops_super.h +++ b/fs/gfs2/ops_super.h | |||
@@ -12,6 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | 14 | ||
15 | extern struct super_operations gfs2_super_ops; | 15 | extern const struct super_operations gfs2_super_ops; |
16 | 16 | ||
17 | #endif /* __OPS_SUPER_DOT_H__ */ | 17 | #endif /* __OPS_SUPER_DOT_H__ */ |
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c index 14b380fb0602..aa0dbd2aac1b 100644 --- a/fs/gfs2/ops_vm.c +++ b/fs/gfs2/ops_vm.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index d0c806b85c86..8bc182c7e2ef 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index ff0846528d54..8d9c08b5c4b6 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index e5707a9f78c2..601eaa1b9ed6 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index e2e0358da335..7c69b98a2e45 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c | |||
@@ -320,7 +320,7 @@ const struct file_operations hfs_dir_operations = { | |||
320 | .release = hfs_dir_release, | 320 | .release = hfs_dir_release, |
321 | }; | 321 | }; |
322 | 322 | ||
323 | struct inode_operations hfs_dir_inode_operations = { | 323 | const struct inode_operations hfs_dir_inode_operations = { |
324 | .create = hfs_create, | 324 | .create = hfs_create, |
325 | .lookup = hfs_lookup, | 325 | .lookup = hfs_lookup, |
326 | .unlink = hfs_unlink, | 326 | .unlink = hfs_unlink, |
diff --git a/fs/hfs/hfs.h b/fs/hfs/hfs.h index 88099ab1a180..1445e3a56ed4 100644 --- a/fs/hfs/hfs.h +++ b/fs/hfs/hfs.h | |||
@@ -83,8 +83,6 @@ | |||
83 | 83 | ||
84 | /*======== HFS structures as they appear on the disk ========*/ | 84 | /*======== HFS structures as they appear on the disk ========*/ |
85 | 85 | ||
86 | #define __packed __attribute__ ((packed)) | ||
87 | |||
88 | /* Pascal-style string of up to 31 characters */ | 86 | /* Pascal-style string of up to 31 characters */ |
89 | struct hfs_name { | 87 | struct hfs_name { |
90 | u8 len; | 88 | u8 len; |
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 735332dfd1b8..147374b6f675 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h | |||
@@ -170,7 +170,7 @@ extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qst | |||
170 | 170 | ||
171 | /* dir.c */ | 171 | /* dir.c */ |
172 | extern const struct file_operations hfs_dir_operations; | 172 | extern const struct file_operations hfs_dir_operations; |
173 | extern struct inode_operations hfs_dir_inode_operations; | 173 | extern const struct inode_operations hfs_dir_inode_operations; |
174 | 174 | ||
175 | /* extent.c */ | 175 | /* extent.c */ |
176 | extern int hfs_ext_keycmp(const btree_key *, const btree_key *); | 176 | extern int hfs_ext_keycmp(const btree_key *, const btree_key *); |
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 5cb7f8fee8d6..fafcba593871 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include "btree.h" | 18 | #include "btree.h" |
19 | 19 | ||
20 | static const struct file_operations hfs_file_operations; | 20 | static const struct file_operations hfs_file_operations; |
21 | static struct inode_operations hfs_file_inode_operations; | 21 | static const struct inode_operations hfs_file_inode_operations; |
22 | 22 | ||
23 | /*================ Variable-like macros ================*/ | 23 | /*================ Variable-like macros ================*/ |
24 | 24 | ||
@@ -612,7 +612,7 @@ static const struct file_operations hfs_file_operations = { | |||
612 | .release = hfs_file_release, | 612 | .release = hfs_file_release, |
613 | }; | 613 | }; |
614 | 614 | ||
615 | static struct inode_operations hfs_file_inode_operations = { | 615 | static const struct inode_operations hfs_file_inode_operations = { |
616 | .lookup = hfs_file_lookup, | 616 | .lookup = hfs_file_lookup, |
617 | .truncate = hfs_file_truncate, | 617 | .truncate = hfs_file_truncate, |
618 | .setattr = hfs_inode_setattr, | 618 | .setattr = hfs_inode_setattr, |
diff --git a/fs/hfs/super.c b/fs/hfs/super.c index a36987966004..623f509f1d47 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c | |||
@@ -154,7 +154,7 @@ static void hfs_destroy_inode(struct inode *inode) | |||
154 | kmem_cache_free(hfs_inode_cachep, HFS_I(inode)); | 154 | kmem_cache_free(hfs_inode_cachep, HFS_I(inode)); |
155 | } | 155 | } |
156 | 156 | ||
157 | static struct super_operations hfs_super_operations = { | 157 | static const struct super_operations hfs_super_operations = { |
158 | .alloc_inode = hfs_alloc_inode, | 158 | .alloc_inode = hfs_alloc_inode, |
159 | .destroy_inode = hfs_destroy_inode, | 159 | .destroy_inode = hfs_destroy_inode, |
160 | .write_inode = hfs_write_inode, | 160 | .write_inode = hfs_write_inode, |
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index f2d7c49ce759..ba117c445e78 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c | |||
@@ -8,7 +8,6 @@ | |||
8 | * Handling of catalog records | 8 | * Handling of catalog records |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/sched.h> | ||
12 | 11 | ||
13 | #include "hfsplus_fs.h" | 12 | #include "hfsplus_fs.h" |
14 | #include "hfsplus_raw.h" | 13 | #include "hfsplus_raw.h" |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index e886ac8460d3..80b5682a2273 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -10,7 +10,6 @@ | |||
10 | 10 | ||
11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/sched.h> | ||
14 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
15 | #include <linux/random.h> | 14 | #include <linux/random.h> |
16 | 15 | ||
@@ -471,7 +470,7 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
471 | return res; | 470 | return res; |
472 | } | 471 | } |
473 | 472 | ||
474 | struct inode_operations hfsplus_dir_inode_operations = { | 473 | const struct inode_operations hfsplus_dir_inode_operations = { |
475 | .lookup = hfsplus_lookup, | 474 | .lookup = hfsplus_lookup, |
476 | .create = hfsplus_create, | 475 | .create = hfsplus_create, |
477 | .link = hfsplus_link, | 476 | .link = hfsplus_link, |
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index 49205531a500..fe99fe8db61a 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h | |||
@@ -15,8 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | 17 | ||
18 | #define __packed __attribute__ ((packed)) | ||
19 | |||
20 | /* Some constants */ | 18 | /* Some constants */ |
21 | #define HFSPLUS_SECTOR_SIZE 512 | 19 | #define HFSPLUS_SECTOR_SIZE 512 |
22 | #define HFSPLUS_SECTOR_SHIFT 9 | 20 | #define HFSPLUS_SECTOR_SHIFT 9 |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 75e8c4d8aac3..642012ac3370 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -268,10 +268,10 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) | |||
268 | return 0; | 268 | return 0; |
269 | } | 269 | } |
270 | 270 | ||
271 | extern struct inode_operations hfsplus_dir_inode_operations; | 271 | extern const struct inode_operations hfsplus_dir_inode_operations; |
272 | extern struct file_operations hfsplus_dir_operations; | 272 | extern struct file_operations hfsplus_dir_operations; |
273 | 273 | ||
274 | static struct inode_operations hfsplus_file_inode_operations = { | 274 | static const struct inode_operations hfsplus_file_inode_operations = { |
275 | .lookup = hfsplus_file_lookup, | 275 | .lookup = hfsplus_file_lookup, |
276 | .truncate = hfsplus_file_truncate, | 276 | .truncate = hfsplus_file_truncate, |
277 | .permission = hfsplus_permission, | 277 | .permission = hfsplus_permission, |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 0f513c6bf843..1a97f9293447 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/sched.h> | ||
15 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
16 | #include <linux/vfs.h> | 15 | #include <linux/vfs.h> |
17 | #include <linux/nls.h> | 16 | #include <linux/nls.h> |
@@ -260,7 +259,7 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) | |||
260 | return 0; | 259 | return 0; |
261 | } | 260 | } |
262 | 261 | ||
263 | static struct super_operations hfsplus_sops = { | 262 | static const struct super_operations hfsplus_sops = { |
264 | .alloc_inode = hfsplus_alloc_inode, | 263 | .alloc_inode = hfsplus_alloc_inode, |
265 | .destroy_inode = hfsplus_destroy_inode, | 264 | .destroy_inode = hfsplus_destroy_inode, |
266 | .read_inode = hfsplus_read_inode, | 265 | .read_inode = hfsplus_read_inode, |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 69a376f35a68..e965eb11d76f 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -52,8 +52,8 @@ static int append = 0; | |||
52 | 52 | ||
53 | #define HOSTFS_SUPER_MAGIC 0x00c0ffee | 53 | #define HOSTFS_SUPER_MAGIC 0x00c0ffee |
54 | 54 | ||
55 | static struct inode_operations hostfs_iops; | 55 | static const struct inode_operations hostfs_iops; |
56 | static struct inode_operations hostfs_dir_iops; | 56 | static const struct inode_operations hostfs_dir_iops; |
57 | static const struct address_space_operations hostfs_link_aops; | 57 | static const struct address_space_operations hostfs_link_aops; |
58 | 58 | ||
59 | #ifndef MODULE | 59 | #ifndef MODULE |
@@ -309,7 +309,7 @@ static void hostfs_read_inode(struct inode *inode) | |||
309 | read_inode(inode); | 309 | read_inode(inode); |
310 | } | 310 | } |
311 | 311 | ||
312 | static struct super_operations hostfs_sbops = { | 312 | static const struct super_operations hostfs_sbops = { |
313 | .alloc_inode = hostfs_alloc_inode, | 313 | .alloc_inode = hostfs_alloc_inode, |
314 | .drop_inode = generic_delete_inode, | 314 | .drop_inode = generic_delete_inode, |
315 | .delete_inode = hostfs_delete_inode, | 315 | .delete_inode = hostfs_delete_inode, |
@@ -880,7 +880,7 @@ int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
880 | return(0); | 880 | return(0); |
881 | } | 881 | } |
882 | 882 | ||
883 | static struct inode_operations hostfs_iops = { | 883 | static const struct inode_operations hostfs_iops = { |
884 | .create = hostfs_create, | 884 | .create = hostfs_create, |
885 | .link = hostfs_link, | 885 | .link = hostfs_link, |
886 | .unlink = hostfs_unlink, | 886 | .unlink = hostfs_unlink, |
@@ -894,7 +894,7 @@ static struct inode_operations hostfs_iops = { | |||
894 | .getattr = hostfs_getattr, | 894 | .getattr = hostfs_getattr, |
895 | }; | 895 | }; |
896 | 896 | ||
897 | static struct inode_operations hostfs_dir_iops = { | 897 | static const struct inode_operations hostfs_dir_iops = { |
898 | .create = hostfs_create, | 898 | .create = hostfs_create, |
899 | .lookup = hostfs_lookup, | 899 | .lookup = hostfs_lookup, |
900 | .link = hostfs_link, | 900 | .link = hostfs_link, |
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index fb4c8915010a..b4eafc0f1e54 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c | |||
@@ -132,7 +132,7 @@ const struct file_operations hpfs_file_ops = | |||
132 | .sendfile = generic_file_sendfile, | 132 | .sendfile = generic_file_sendfile, |
133 | }; | 133 | }; |
134 | 134 | ||
135 | struct inode_operations hpfs_file_iops = | 135 | const struct inode_operations hpfs_file_iops = |
136 | { | 136 | { |
137 | .truncate = hpfs_truncate, | 137 | .truncate = hpfs_truncate, |
138 | .setattr = hpfs_notify_change, | 138 | .setattr = hpfs_notify_change, |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 1c07aa82d327..42ff60ccf2a9 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
@@ -266,7 +266,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int); | |||
266 | 266 | ||
267 | int hpfs_file_fsync(struct file *, struct dentry *, int); | 267 | int hpfs_file_fsync(struct file *, struct dentry *, int); |
268 | extern const struct file_operations hpfs_file_ops; | 268 | extern const struct file_operations hpfs_file_ops; |
269 | extern struct inode_operations hpfs_file_iops; | 269 | extern const struct inode_operations hpfs_file_iops; |
270 | extern const struct address_space_operations hpfs_aops; | 270 | extern const struct address_space_operations hpfs_aops; |
271 | 271 | ||
272 | /* inode.c */ | 272 | /* inode.c */ |
@@ -302,7 +302,7 @@ void hpfs_decide_conv(struct inode *, unsigned char *, unsigned); | |||
302 | 302 | ||
303 | /* namei.c */ | 303 | /* namei.c */ |
304 | 304 | ||
305 | extern struct inode_operations hpfs_dir_iops; | 305 | extern const struct inode_operations hpfs_dir_iops; |
306 | extern const struct address_space_operations hpfs_symlink_aops; | 306 | extern const struct address_space_operations hpfs_symlink_aops; |
307 | 307 | ||
308 | static inline struct hpfs_inode_info *hpfs_i(struct inode *inode) | 308 | static inline struct hpfs_inode_info *hpfs_i(struct inode *inode) |
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 2507e7393f3c..9953cf9a2f16 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c | |||
@@ -659,7 +659,7 @@ end1: | |||
659 | return err; | 659 | return err; |
660 | } | 660 | } |
661 | 661 | ||
662 | struct inode_operations hpfs_dir_iops = | 662 | const struct inode_operations hpfs_dir_iops = |
663 | { | 663 | { |
664 | .create = hpfs_create, | 664 | .create = hpfs_create, |
665 | .lookup = hpfs_lookup, | 665 | .lookup = hpfs_lookup, |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index d4abc1a1d566..e0174e338526 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
@@ -426,7 +426,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) | |||
426 | 426 | ||
427 | /* Super operations */ | 427 | /* Super operations */ |
428 | 428 | ||
429 | static struct super_operations hpfs_sops = | 429 | static const struct super_operations hpfs_sops = |
430 | { | 430 | { |
431 | .alloc_inode = hpfs_alloc_inode, | 431 | .alloc_inode = hpfs_alloc_inode, |
432 | .destroy_inode = hpfs_destroy_inode, | 432 | .destroy_inode = hpfs_destroy_inode, |
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index afd340a45da4..affb7412125e 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c | |||
@@ -43,7 +43,7 @@ static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) | |||
43 | 43 | ||
44 | #define HPPFS_SUPER_MAGIC 0xb00000ee | 44 | #define HPPFS_SUPER_MAGIC 0xb00000ee |
45 | 45 | ||
46 | static struct super_operations hppfs_sbops; | 46 | static const struct super_operations hppfs_sbops; |
47 | 47 | ||
48 | static int is_pid(struct dentry *dentry) | 48 | static int is_pid(struct dentry *dentry) |
49 | { | 49 | { |
@@ -212,7 +212,7 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | |||
212 | return(ERR_PTR(err)); | 212 | return(ERR_PTR(err)); |
213 | } | 213 | } |
214 | 214 | ||
215 | static struct inode_operations hppfs_file_iops = { | 215 | static const struct inode_operations hppfs_file_iops = { |
216 | }; | 216 | }; |
217 | 217 | ||
218 | static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, | 218 | static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, |
@@ -649,7 +649,7 @@ static void hppfs_destroy_inode(struct inode *inode) | |||
649 | kfree(HPPFS_I(inode)); | 649 | kfree(HPPFS_I(inode)); |
650 | } | 650 | } |
651 | 651 | ||
652 | static struct super_operations hppfs_sbops = { | 652 | static const struct super_operations hppfs_sbops = { |
653 | .alloc_inode = hppfs_alloc_inode, | 653 | .alloc_inode = hppfs_alloc_inode, |
654 | .destroy_inode = hppfs_destroy_inode, | 654 | .destroy_inode = hppfs_destroy_inode, |
655 | .read_inode = hppfs_read_inode, | 655 | .read_inode = hppfs_read_inode, |
@@ -693,11 +693,11 @@ static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
693 | return ret; | 693 | return ret; |
694 | } | 694 | } |
695 | 695 | ||
696 | static struct inode_operations hppfs_dir_iops = { | 696 | static const struct inode_operations hppfs_dir_iops = { |
697 | .lookup = hppfs_lookup, | 697 | .lookup = hppfs_lookup, |
698 | }; | 698 | }; |
699 | 699 | ||
700 | static struct inode_operations hppfs_link_iops = { | 700 | static const struct inode_operations hppfs_link_iops = { |
701 | .readlink = hppfs_readlink, | 701 | .readlink = hppfs_readlink, |
702 | .follow_link = hppfs_follow_link, | 702 | .follow_link = hppfs_follow_link, |
703 | }; | 703 | }; |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 4f4cd132b571..8c718a3d413f 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -33,11 +33,11 @@ | |||
33 | /* some random number */ | 33 | /* some random number */ |
34 | #define HUGETLBFS_MAGIC 0x958458f6 | 34 | #define HUGETLBFS_MAGIC 0x958458f6 |
35 | 35 | ||
36 | static struct super_operations hugetlbfs_ops; | 36 | static const struct super_operations hugetlbfs_ops; |
37 | static const struct address_space_operations hugetlbfs_aops; | 37 | static const struct address_space_operations hugetlbfs_aops; |
38 | const struct file_operations hugetlbfs_file_operations; | 38 | const struct file_operations hugetlbfs_file_operations; |
39 | static struct inode_operations hugetlbfs_dir_inode_operations; | 39 | static const struct inode_operations hugetlbfs_dir_inode_operations; |
40 | static struct inode_operations hugetlbfs_inode_operations; | 40 | static const struct inode_operations hugetlbfs_inode_operations; |
41 | 41 | ||
42 | static struct backing_dev_info hugetlbfs_backing_dev_info = { | 42 | static struct backing_dev_info hugetlbfs_backing_dev_info = { |
43 | .ra_pages = 0, /* No readahead */ | 43 | .ra_pages = 0, /* No readahead */ |
@@ -449,10 +449,13 @@ static int hugetlbfs_symlink(struct inode *dir, | |||
449 | } | 449 | } |
450 | 450 | ||
451 | /* | 451 | /* |
452 | * For direct-IO reads into hugetlb pages | 452 | * mark the head page dirty |
453 | */ | 453 | */ |
454 | static int hugetlbfs_set_page_dirty(struct page *page) | 454 | static int hugetlbfs_set_page_dirty(struct page *page) |
455 | { | 455 | { |
456 | struct page *head = (struct page *)page_private(page); | ||
457 | |||
458 | SetPageDirty(head); | ||
456 | return 0; | 459 | return 0; |
457 | } | 460 | } |
458 | 461 | ||
@@ -560,7 +563,7 @@ const struct file_operations hugetlbfs_file_operations = { | |||
560 | .get_unmapped_area = hugetlb_get_unmapped_area, | 563 | .get_unmapped_area = hugetlb_get_unmapped_area, |
561 | }; | 564 | }; |
562 | 565 | ||
563 | static struct inode_operations hugetlbfs_dir_inode_operations = { | 566 | static const struct inode_operations hugetlbfs_dir_inode_operations = { |
564 | .create = hugetlbfs_create, | 567 | .create = hugetlbfs_create, |
565 | .lookup = simple_lookup, | 568 | .lookup = simple_lookup, |
566 | .link = simple_link, | 569 | .link = simple_link, |
@@ -573,11 +576,11 @@ static struct inode_operations hugetlbfs_dir_inode_operations = { | |||
573 | .setattr = hugetlbfs_setattr, | 576 | .setattr = hugetlbfs_setattr, |
574 | }; | 577 | }; |
575 | 578 | ||
576 | static struct inode_operations hugetlbfs_inode_operations = { | 579 | static const struct inode_operations hugetlbfs_inode_operations = { |
577 | .setattr = hugetlbfs_setattr, | 580 | .setattr = hugetlbfs_setattr, |
578 | }; | 581 | }; |
579 | 582 | ||
580 | static struct super_operations hugetlbfs_ops = { | 583 | static const struct super_operations hugetlbfs_ops = { |
581 | .alloc_inode = hugetlbfs_alloc_inode, | 584 | .alloc_inode = hugetlbfs_alloc_inode, |
582 | .destroy_inode = hugetlbfs_destroy_inode, | 585 | .destroy_inode = hugetlbfs_destroy_inode, |
583 | .statfs = hugetlbfs_statfs, | 586 | .statfs = hugetlbfs_statfs, |
diff --git a/fs/inode.c b/fs/inode.c index bf21dc6d0dbd..5abb097ab1b0 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -414,7 +414,8 @@ static void prune_icache(int nr_to_scan) | |||
414 | __iget(inode); | 414 | __iget(inode); |
415 | spin_unlock(&inode_lock); | 415 | spin_unlock(&inode_lock); |
416 | if (remove_inode_buffers(inode)) | 416 | if (remove_inode_buffers(inode)) |
417 | reap += invalidate_inode_pages(&inode->i_data); | 417 | reap += invalidate_mapping_pages(&inode->i_data, |
418 | 0, -1); | ||
418 | iput(inode); | 419 | iput(inode); |
419 | spin_lock(&inode_lock); | 420 | spin_lock(&inode_lock); |
420 | 421 | ||
@@ -709,7 +710,7 @@ EXPORT_SYMBOL(iunique); | |||
709 | struct inode *igrab(struct inode *inode) | 710 | struct inode *igrab(struct inode *inode) |
710 | { | 711 | { |
711 | spin_lock(&inode_lock); | 712 | spin_lock(&inode_lock); |
712 | if (!(inode->i_state & (I_FREEING|I_WILL_FREE))) | 713 | if (!(inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE))) |
713 | __iget(inode); | 714 | __iget(inode); |
714 | else | 715 | else |
715 | /* | 716 | /* |
@@ -999,7 +1000,7 @@ EXPORT_SYMBOL(remove_inode_hash); | |||
999 | */ | 1000 | */ |
1000 | void generic_delete_inode(struct inode *inode) | 1001 | void generic_delete_inode(struct inode *inode) |
1001 | { | 1002 | { |
1002 | struct super_operations *op = inode->i_sb->s_op; | 1003 | const struct super_operations *op = inode->i_sb->s_op; |
1003 | 1004 | ||
1004 | list_del_init(&inode->i_list); | 1005 | list_del_init(&inode->i_list); |
1005 | list_del_init(&inode->i_sb_list); | 1006 | list_del_init(&inode->i_sb_list); |
@@ -1092,7 +1093,7 @@ EXPORT_SYMBOL_GPL(generic_drop_inode); | |||
1092 | */ | 1093 | */ |
1093 | static inline void iput_final(struct inode *inode) | 1094 | static inline void iput_final(struct inode *inode) |
1094 | { | 1095 | { |
1095 | struct super_operations *op = inode->i_sb->s_op; | 1096 | const struct super_operations *op = inode->i_sb->s_op; |
1096 | void (*drop)(struct inode *) = generic_drop_inode; | 1097 | void (*drop)(struct inode *) = generic_drop_inode; |
1097 | 1098 | ||
1098 | if (op && op->drop_inode) | 1099 | if (op && op->drop_inode) |
@@ -1112,7 +1113,7 @@ static inline void iput_final(struct inode *inode) | |||
1112 | void iput(struct inode *inode) | 1113 | void iput(struct inode *inode) |
1113 | { | 1114 | { |
1114 | if (inode) { | 1115 | if (inode) { |
1115 | struct super_operations *op = inode->i_sb->s_op; | 1116 | const struct super_operations *op = inode->i_sb->s_op; |
1116 | 1117 | ||
1117 | BUG_ON(inode->i_state == I_CLEAR); | 1118 | BUG_ON(inode->i_state == I_CLEAR); |
1118 | 1119 | ||
@@ -1160,11 +1161,9 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry) | |||
1160 | struct inode *inode = dentry->d_inode; | 1161 | struct inode *inode = dentry->d_inode; |
1161 | struct timespec now; | 1162 | struct timespec now; |
1162 | 1163 | ||
1163 | if (IS_RDONLY(inode)) | ||
1164 | return; | ||
1165 | if (inode->i_flags & S_NOATIME) | 1164 | if (inode->i_flags & S_NOATIME) |
1166 | return; | 1165 | return; |
1167 | if (inode->i_sb->s_flags & MS_NOATIME) | 1166 | if (IS_NOATIME(inode)) |
1168 | return; | 1167 | return; |
1169 | if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)) | 1168 | if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)) |
1170 | return; | 1169 | return; |
@@ -1252,33 +1251,6 @@ int inode_needs_sync(struct inode *inode) | |||
1252 | 1251 | ||
1253 | EXPORT_SYMBOL(inode_needs_sync); | 1252 | EXPORT_SYMBOL(inode_needs_sync); |
1254 | 1253 | ||
1255 | /* | ||
1256 | * Quota functions that want to walk the inode lists.. | ||
1257 | */ | ||
1258 | #ifdef CONFIG_QUOTA | ||
1259 | |||
1260 | void remove_dquot_ref(struct super_block *sb, int type, | ||
1261 | struct list_head *tofree_head) | ||
1262 | { | ||
1263 | struct inode *inode; | ||
1264 | |||
1265 | if (!sb->dq_op) | ||
1266 | return; /* nothing to do */ | ||
1267 | spin_lock(&inode_lock); /* This lock is for inodes code */ | ||
1268 | |||
1269 | /* | ||
1270 | * We don't have to lock against quota code - test IS_QUOTAINIT is | ||
1271 | * just for speedup... | ||
1272 | */ | ||
1273 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) | ||
1274 | if (!IS_NOQUOTA(inode)) | ||
1275 | remove_inode_dquot_ref(inode, type, tofree_head); | ||
1276 | |||
1277 | spin_unlock(&inode_lock); | ||
1278 | } | ||
1279 | |||
1280 | #endif | ||
1281 | |||
1282 | int inode_wait(void *word) | 1254 | int inode_wait(void *word) |
1283 | { | 1255 | { |
1284 | schedule(); | 1256 | schedule(); |
diff --git a/fs/inotify_user.c b/fs/inotify_user.c index 55f6da55b7c0..9f2224f65a18 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c | |||
@@ -455,8 +455,16 @@ static ssize_t inotify_read(struct file *file, char __user *buf, | |||
455 | break; | 455 | break; |
456 | 456 | ||
457 | kevent = inotify_dev_get_event(dev); | 457 | kevent = inotify_dev_get_event(dev); |
458 | if (event_size + kevent->event.len > count) | 458 | if (event_size + kevent->event.len > count) { |
459 | if (ret == 0 && count > 0) { | ||
460 | /* | ||
461 | * could not get a single event because we | ||
462 | * didn't have enough buffer space. | ||
463 | */ | ||
464 | ret = -EINVAL; | ||
465 | } | ||
459 | break; | 466 | break; |
467 | } | ||
460 | 468 | ||
461 | if (copy_to_user(buf, &kevent->event, event_size)) { | 469 | if (copy_to_user(buf, &kevent->event, event_size)) { |
462 | ret = -EFAULT; | 470 | ret = -EFAULT; |
diff --git a/fs/ioprio.c b/fs/ioprio.c index 89e8da112a75..10d2c211d18b 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c | |||
@@ -60,6 +60,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) | |||
60 | int data = IOPRIO_PRIO_DATA(ioprio); | 60 | int data = IOPRIO_PRIO_DATA(ioprio); |
61 | struct task_struct *p, *g; | 61 | struct task_struct *p, *g; |
62 | struct user_struct *user; | 62 | struct user_struct *user; |
63 | struct pid *pgrp; | ||
63 | int ret; | 64 | int ret; |
64 | 65 | ||
65 | switch (class) { | 66 | switch (class) { |
@@ -98,12 +99,14 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) | |||
98 | break; | 99 | break; |
99 | case IOPRIO_WHO_PGRP: | 100 | case IOPRIO_WHO_PGRP: |
100 | if (!who) | 101 | if (!who) |
101 | who = process_group(current); | 102 | pgrp = task_pgrp(current); |
102 | do_each_task_pid(who, PIDTYPE_PGID, p) { | 103 | else |
104 | pgrp = find_pid(who); | ||
105 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { | ||
103 | ret = set_task_ioprio(p, ioprio); | 106 | ret = set_task_ioprio(p, ioprio); |
104 | if (ret) | 107 | if (ret) |
105 | break; | 108 | break; |
106 | } while_each_task_pid(who, PIDTYPE_PGID, p); | 109 | } while_each_pid_task(pgrp, PIDTYPE_PGID, p); |
107 | break; | 110 | break; |
108 | case IOPRIO_WHO_USER: | 111 | case IOPRIO_WHO_USER: |
109 | if (!who) | 112 | if (!who) |
@@ -167,6 +170,7 @@ asmlinkage long sys_ioprio_get(int which, int who) | |||
167 | { | 170 | { |
168 | struct task_struct *g, *p; | 171 | struct task_struct *g, *p; |
169 | struct user_struct *user; | 172 | struct user_struct *user; |
173 | struct pid *pgrp; | ||
170 | int ret = -ESRCH; | 174 | int ret = -ESRCH; |
171 | int tmpio; | 175 | int tmpio; |
172 | 176 | ||
@@ -182,8 +186,10 @@ asmlinkage long sys_ioprio_get(int which, int who) | |||
182 | break; | 186 | break; |
183 | case IOPRIO_WHO_PGRP: | 187 | case IOPRIO_WHO_PGRP: |
184 | if (!who) | 188 | if (!who) |
185 | who = process_group(current); | 189 | pgrp = task_pgrp(current); |
186 | do_each_task_pid(who, PIDTYPE_PGID, p) { | 190 | else |
191 | pgrp = find_pid(who); | ||
192 | do_each_pid_task(pgrp, PIDTYPE_PGID, p) { | ||
187 | tmpio = get_task_ioprio(p); | 193 | tmpio = get_task_ioprio(p); |
188 | if (tmpio < 0) | 194 | if (tmpio < 0) |
189 | continue; | 195 | continue; |
@@ -191,7 +197,7 @@ asmlinkage long sys_ioprio_get(int which, int who) | |||
191 | ret = tmpio; | 197 | ret = tmpio; |
192 | else | 198 | else |
193 | ret = ioprio_best(ret, tmpio); | 199 | ret = ioprio_best(ret, tmpio); |
194 | } while_each_task_pid(who, PIDTYPE_PGID, p); | 200 | } while_each_pid_task(pgrp, PIDTYPE_PGID, p); |
195 | break; | 201 | break; |
196 | case IOPRIO_WHO_USER: | 202 | case IOPRIO_WHO_USER: |
197 | if (!who) | 203 | if (!who) |
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 4af2548f97a9..0e94c31cad9b 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c | |||
@@ -24,7 +24,7 @@ const struct file_operations isofs_dir_operations = | |||
24 | /* | 24 | /* |
25 | * directories can handle most operations... | 25 | * directories can handle most operations... |
26 | */ | 26 | */ |
27 | struct inode_operations isofs_dir_inode_operations = | 27 | const struct inode_operations isofs_dir_inode_operations = |
28 | { | 28 | { |
29 | .lookup = isofs_lookup, | 29 | .lookup = isofs_lookup, |
30 | }; | 30 | }; |
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index ea55b6c469ec..64a96cdfe3a4 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
@@ -106,7 +106,7 @@ static int isofs_remount(struct super_block *sb, int *flags, char *data) | |||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | static struct super_operations isofs_sops = { | 109 | static const struct super_operations isofs_sops = { |
110 | .alloc_inode = isofs_alloc_inode, | 110 | .alloc_inode = isofs_alloc_inode, |
111 | .destroy_inode = isofs_destroy_inode, | 111 | .destroy_inode = isofs_destroy_inode, |
112 | .read_inode = isofs_read_inode, | 112 | .read_inode = isofs_read_inode, |
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index e6308c8b5735..efe2872cd4e3 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h | |||
@@ -174,7 +174,7 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de, | |||
174 | } | 174 | } |
175 | } | 175 | } |
176 | 176 | ||
177 | extern struct inode_operations isofs_dir_inode_operations; | 177 | extern const struct inode_operations isofs_dir_inode_operations; |
178 | extern const struct file_operations isofs_dir_operations; | 178 | extern const struct file_operations isofs_dir_operations; |
179 | extern const struct address_space_operations isofs_symlink_aops; | 179 | extern const struct address_space_operations isofs_symlink_aops; |
180 | extern struct export_operations isofs_export_ops; | 180 | extern struct export_operations isofs_export_ops; |
diff --git a/fs/jffs/Makefile b/fs/jffs/Makefile deleted file mode 100644 index 9c1c0bb59696..000000000000 --- a/fs/jffs/Makefile +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for the linux Journalling Flash FileSystem (JFFS) routines. | ||
3 | # | ||
4 | # $Id: Makefile,v 1.11 2001/09/25 20:59:41 dwmw2 Exp $ | ||
5 | # | ||
6 | |||
7 | obj-$(CONFIG_JFFS_FS) += jffs.o | ||
8 | |||
9 | jffs-y := jffs_fm.o intrep.o inode-v23.o | ||
10 | jffs-$(CONFIG_JFFS_PROC_FS) += jffs_proc.o | ||
11 | jffs-objs := $(jffs-y) | ||
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c deleted file mode 100644 index 43baa1afa021..000000000000 --- a/fs/jffs/inode-v23.c +++ /dev/null | |||
@@ -1,1847 +0,0 @@ | |||
1 | /* | ||
2 | * JFFS -- Journalling Flash File System, Linux implementation. | ||
3 | * | ||
4 | * Copyright (C) 1999, 2000 Axis Communications AB. | ||
5 | * | ||
6 | * Created by Finn Hakansson <finn@axis.com>. | ||
7 | * | ||
8 | * This is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * $Id: inode-v23.c,v 1.70 2001/10/02 09:16:02 dwmw2 Exp $ | ||
14 | * | ||
15 | * Ported to Linux 2.3.x and MTD: | ||
16 | * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB | ||
17 | * | ||
18 | * Copyright 2000, 2001 Red Hat, Inc. | ||
19 | */ | ||
20 | |||
21 | /* inode.c -- Contains the code that is called from the VFS. */ | ||
22 | |||
23 | /* TODO-ALEX: | ||
24 | * uid and gid are just 16 bit. | ||
25 | * jffs_file_write reads from user-space pointers without xx_from_user | ||
26 | * maybe other stuff do to. | ||
27 | */ | ||
28 | |||
29 | #include <linux/time.h> | ||
30 | |||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/types.h> | ||
34 | #include <linux/errno.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/jffs.h> | ||
37 | #include <linux/fs.h> | ||
38 | #include <linux/smp_lock.h> | ||
39 | #include <linux/ioctl.h> | ||
40 | #include <linux/stat.h> | ||
41 | #include <linux/blkdev.h> | ||
42 | #include <linux/quotaops.h> | ||
43 | #include <linux/highmem.h> | ||
44 | #include <linux/vfs.h> | ||
45 | #include <linux/mutex.h> | ||
46 | #include <asm/byteorder.h> | ||
47 | #include <asm/uaccess.h> | ||
48 | |||
49 | #include "jffs_fm.h" | ||
50 | #include "intrep.h" | ||
51 | #ifdef CONFIG_JFFS_PROC_FS | ||
52 | #include "jffs_proc.h" | ||
53 | #endif | ||
54 | |||
55 | static int jffs_remove(struct inode *dir, struct dentry *dentry, int type); | ||
56 | |||
57 | static struct super_operations jffs_ops; | ||
58 | static const struct file_operations jffs_file_operations; | ||
59 | static struct inode_operations jffs_file_inode_operations; | ||
60 | static const struct file_operations jffs_dir_operations; | ||
61 | static struct inode_operations jffs_dir_inode_operations; | ||
62 | static const struct address_space_operations jffs_address_operations; | ||
63 | |||
64 | struct kmem_cache *node_cache = NULL; | ||
65 | struct kmem_cache *fm_cache = NULL; | ||
66 | |||
67 | /* Called by the VFS at mount time to initialize the whole file system. */ | ||
68 | static int jffs_fill_super(struct super_block *sb, void *data, int silent) | ||
69 | { | ||
70 | struct inode *root_inode; | ||
71 | struct jffs_control *c; | ||
72 | |||
73 | sb->s_flags |= MS_NODIRATIME; | ||
74 | |||
75 | D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n", | ||
76 | sb->s_id)); | ||
77 | |||
78 | if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { | ||
79 | printk(KERN_WARNING "JFFS: Trying to mount a " | ||
80 | "non-mtd device.\n"); | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
84 | sb->s_blocksize = PAGE_CACHE_SIZE; | ||
85 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | ||
86 | sb->s_fs_info = (void *) 0; | ||
87 | sb->s_maxbytes = 0xFFFFFFFF; | ||
88 | |||
89 | /* Build the file system. */ | ||
90 | if (jffs_build_fs(sb) < 0) { | ||
91 | goto jffs_sb_err1; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * set up enough so that we can read an inode | ||
96 | */ | ||
97 | sb->s_magic = JFFS_MAGIC_SB_BITMASK; | ||
98 | sb->s_op = &jffs_ops; | ||
99 | |||
100 | root_inode = iget(sb, JFFS_MIN_INO); | ||
101 | if (!root_inode) | ||
102 | goto jffs_sb_err2; | ||
103 | |||
104 | /* Get the root directory of this file system. */ | ||
105 | if (!(sb->s_root = d_alloc_root(root_inode))) { | ||
106 | goto jffs_sb_err3; | ||
107 | } | ||
108 | |||
109 | c = (struct jffs_control *) sb->s_fs_info; | ||
110 | |||
111 | #ifdef CONFIG_JFFS_PROC_FS | ||
112 | /* Set up the jffs proc file system. */ | ||
113 | if (jffs_register_jffs_proc_dir(MINOR(sb->s_dev), c) < 0) { | ||
114 | printk(KERN_WARNING "JFFS: Failed to initialize the JFFS " | ||
115 | "proc file system for device %s.\n", | ||
116 | sb->s_id); | ||
117 | } | ||
118 | #endif | ||
119 | |||
120 | /* Set the Garbage Collection thresholds */ | ||
121 | |||
122 | /* GC if free space goes below 5% of the total size */ | ||
123 | c->gc_minfree_threshold = c->fmc->flash_size / 20; | ||
124 | |||
125 | if (c->gc_minfree_threshold < c->fmc->sector_size) | ||
126 | c->gc_minfree_threshold = c->fmc->sector_size; | ||
127 | |||
128 | /* GC if dirty space exceeds 33% of the total size. */ | ||
129 | c->gc_maxdirty_threshold = c->fmc->flash_size / 3; | ||
130 | |||
131 | if (c->gc_maxdirty_threshold < c->fmc->sector_size) | ||
132 | c->gc_maxdirty_threshold = c->fmc->sector_size; | ||
133 | |||
134 | |||
135 | c->thread_pid = kernel_thread (jffs_garbage_collect_thread, | ||
136 | (void *) c, | ||
137 | CLONE_KERNEL); | ||
138 | D1(printk(KERN_NOTICE "JFFS: GC thread pid=%d.\n", (int) c->thread_pid)); | ||
139 | |||
140 | D1(printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n", | ||
141 | sb->s_id)); | ||
142 | return 0; | ||
143 | |||
144 | jffs_sb_err3: | ||
145 | iput(root_inode); | ||
146 | jffs_sb_err2: | ||
147 | jffs_cleanup_control((struct jffs_control *)sb->s_fs_info); | ||
148 | jffs_sb_err1: | ||
149 | printk(KERN_WARNING "JFFS: Failed to mount device %s.\n", | ||
150 | sb->s_id); | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | |||
154 | |||
155 | /* This function is called when the file system is umounted. */ | ||
156 | static void | ||
157 | jffs_put_super(struct super_block *sb) | ||
158 | { | ||
159 | struct jffs_control *c = (struct jffs_control *) sb->s_fs_info; | ||
160 | |||
161 | D2(printk("jffs_put_super()\n")); | ||
162 | |||
163 | #ifdef CONFIG_JFFS_PROC_FS | ||
164 | jffs_unregister_jffs_proc_dir(c); | ||
165 | #endif | ||
166 | |||
167 | if (c->gc_task) { | ||
168 | D1(printk (KERN_NOTICE "jffs_put_super(): Telling gc thread to die.\n")); | ||
169 | send_sig(SIGKILL, c->gc_task, 1); | ||
170 | } | ||
171 | wait_for_completion(&c->gc_thread_comp); | ||
172 | |||
173 | D1(printk (KERN_NOTICE "jffs_put_super(): Successfully waited on thread.\n")); | ||
174 | |||
175 | jffs_cleanup_control((struct jffs_control *)sb->s_fs_info); | ||
176 | D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n", | ||
177 | sb->s_id)); | ||
178 | } | ||
179 | |||
180 | |||
181 | /* This function is called when user commands like chmod, chgrp and | ||
182 | chown are executed. System calls like trunc() results in a call | ||
183 | to this function. */ | ||
184 | static int | ||
185 | jffs_setattr(struct dentry *dentry, struct iattr *iattr) | ||
186 | { | ||
187 | struct inode *inode = dentry->d_inode; | ||
188 | struct jffs_raw_inode raw_inode; | ||
189 | struct jffs_control *c; | ||
190 | struct jffs_fmcontrol *fmc; | ||
191 | struct jffs_file *f; | ||
192 | struct jffs_node *new_node; | ||
193 | int update_all; | ||
194 | int res = 0; | ||
195 | int recoverable = 0; | ||
196 | |||
197 | lock_kernel(); | ||
198 | |||
199 | if ((res = inode_change_ok(inode, iattr))) | ||
200 | goto out; | ||
201 | |||
202 | c = (struct jffs_control *)inode->i_sb->s_fs_info; | ||
203 | fmc = c->fmc; | ||
204 | |||
205 | D3(printk (KERN_NOTICE "notify_change(): down biglock\n")); | ||
206 | mutex_lock(&fmc->biglock); | ||
207 | |||
208 | f = jffs_find_file(c, inode->i_ino); | ||
209 | |||
210 | ASSERT(if (!f) { | ||
211 | printk("jffs_setattr(): Invalid inode number: %lu\n", | ||
212 | inode->i_ino); | ||
213 | D3(printk (KERN_NOTICE "notify_change(): up biglock\n")); | ||
214 | mutex_unlock(&fmc->biglock); | ||
215 | res = -EINVAL; | ||
216 | goto out; | ||
217 | }); | ||
218 | |||
219 | D1(printk("***jffs_setattr(): file: \"%s\", ino: %u\n", | ||
220 | f->name, f->ino)); | ||
221 | |||
222 | update_all = iattr->ia_valid & ATTR_FORCE; | ||
223 | |||
224 | if ( (update_all || iattr->ia_valid & ATTR_SIZE) | ||
225 | && (iattr->ia_size + 128 < f->size) ) { | ||
226 | /* We're shrinking the file by more than 128 bytes. | ||
227 | We'll be able to GC and recover this space, so | ||
228 | allow it to go into the reserved space. */ | ||
229 | recoverable = 1; | ||
230 | } | ||
231 | |||
232 | if (!(new_node = jffs_alloc_node())) { | ||
233 | D(printk("jffs_setattr(): Allocation failed!\n")); | ||
234 | D3(printk (KERN_NOTICE "notify_change(): up biglock\n")); | ||
235 | mutex_unlock(&fmc->biglock); | ||
236 | res = -ENOMEM; | ||
237 | goto out; | ||
238 | } | ||
239 | |||
240 | new_node->data_offset = 0; | ||
241 | new_node->removed_size = 0; | ||
242 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
243 | raw_inode.ino = f->ino; | ||
244 | raw_inode.pino = f->pino; | ||
245 | raw_inode.mode = f->mode; | ||
246 | raw_inode.uid = f->uid; | ||
247 | raw_inode.gid = f->gid; | ||
248 | raw_inode.atime = f->atime; | ||
249 | raw_inode.mtime = f->mtime; | ||
250 | raw_inode.ctime = f->ctime; | ||
251 | raw_inode.dsize = 0; | ||
252 | raw_inode.offset = 0; | ||
253 | raw_inode.rsize = 0; | ||
254 | raw_inode.dsize = 0; | ||
255 | raw_inode.nsize = f->nsize; | ||
256 | raw_inode.nlink = f->nlink; | ||
257 | raw_inode.spare = 0; | ||
258 | raw_inode.rename = 0; | ||
259 | raw_inode.deleted = 0; | ||
260 | |||
261 | if (update_all || iattr->ia_valid & ATTR_MODE) { | ||
262 | raw_inode.mode = iattr->ia_mode; | ||
263 | inode->i_mode = iattr->ia_mode; | ||
264 | } | ||
265 | if (update_all || iattr->ia_valid & ATTR_UID) { | ||
266 | raw_inode.uid = iattr->ia_uid; | ||
267 | inode->i_uid = iattr->ia_uid; | ||
268 | } | ||
269 | if (update_all || iattr->ia_valid & ATTR_GID) { | ||
270 | raw_inode.gid = iattr->ia_gid; | ||
271 | inode->i_gid = iattr->ia_gid; | ||
272 | } | ||
273 | if (update_all || iattr->ia_valid & ATTR_SIZE) { | ||
274 | int len; | ||
275 | D1(printk("jffs_notify_change(): Changing size " | ||
276 | "to %lu bytes!\n", (long)iattr->ia_size)); | ||
277 | raw_inode.offset = iattr->ia_size; | ||
278 | |||
279 | /* Calculate how many bytes need to be removed from | ||
280 | the end. */ | ||
281 | if (f->size < iattr->ia_size) { | ||
282 | len = 0; | ||
283 | } | ||
284 | else { | ||
285 | len = f->size - iattr->ia_size; | ||
286 | } | ||
287 | |||
288 | raw_inode.rsize = len; | ||
289 | |||
290 | /* The updated node will be a removal node, with | ||
291 | base at the new size and size of the nbr of bytes | ||
292 | to be removed. */ | ||
293 | new_node->data_offset = iattr->ia_size; | ||
294 | new_node->removed_size = len; | ||
295 | inode->i_size = iattr->ia_size; | ||
296 | inode->i_blocks = (inode->i_size + 511) >> 9; | ||
297 | |||
298 | if (len) { | ||
299 | invalidate_inode_pages(inode->i_mapping); | ||
300 | } | ||
301 | inode->i_ctime = CURRENT_TIME_SEC; | ||
302 | inode->i_mtime = inode->i_ctime; | ||
303 | } | ||
304 | if (update_all || iattr->ia_valid & ATTR_ATIME) { | ||
305 | raw_inode.atime = iattr->ia_atime.tv_sec; | ||
306 | inode->i_atime = iattr->ia_atime; | ||
307 | } | ||
308 | if (update_all || iattr->ia_valid & ATTR_MTIME) { | ||
309 | raw_inode.mtime = iattr->ia_mtime.tv_sec; | ||
310 | inode->i_mtime = iattr->ia_mtime; | ||
311 | } | ||
312 | if (update_all || iattr->ia_valid & ATTR_CTIME) { | ||
313 | raw_inode.ctime = iattr->ia_ctime.tv_sec; | ||
314 | inode->i_ctime = iattr->ia_ctime; | ||
315 | } | ||
316 | |||
317 | /* Write this node to the flash. */ | ||
318 | if ((res = jffs_write_node(c, new_node, &raw_inode, f->name, NULL, recoverable, f)) < 0) { | ||
319 | D(printk("jffs_notify_change(): The write failed!\n")); | ||
320 | jffs_free_node(new_node); | ||
321 | D3(printk (KERN_NOTICE "n_c(): up biglock\n")); | ||
322 | mutex_unlock(&c->fmc->biglock); | ||
323 | goto out; | ||
324 | } | ||
325 | |||
326 | jffs_insert_node(c, f, &raw_inode, NULL, new_node); | ||
327 | |||
328 | mark_inode_dirty(inode); | ||
329 | D3(printk (KERN_NOTICE "n_c(): up biglock\n")); | ||
330 | mutex_unlock(&c->fmc->biglock); | ||
331 | out: | ||
332 | unlock_kernel(); | ||
333 | return res; | ||
334 | } /* jffs_notify_change() */ | ||
335 | |||
336 | |||
337 | static struct inode * | ||
338 | jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, | ||
339 | int * err) | ||
340 | { | ||
341 | struct super_block * sb; | ||
342 | struct inode * inode; | ||
343 | struct jffs_control *c; | ||
344 | struct jffs_file *f; | ||
345 | |||
346 | sb = dir->i_sb; | ||
347 | inode = new_inode(sb); | ||
348 | if (!inode) { | ||
349 | *err = -ENOMEM; | ||
350 | return NULL; | ||
351 | } | ||
352 | |||
353 | c = (struct jffs_control *)sb->s_fs_info; | ||
354 | |||
355 | inode->i_ino = raw_inode->ino; | ||
356 | inode->i_mode = raw_inode->mode; | ||
357 | inode->i_nlink = raw_inode->nlink; | ||
358 | inode->i_uid = raw_inode->uid; | ||
359 | inode->i_gid = raw_inode->gid; | ||
360 | inode->i_size = raw_inode->dsize; | ||
361 | inode->i_atime.tv_sec = raw_inode->atime; | ||
362 | inode->i_mtime.tv_sec = raw_inode->mtime; | ||
363 | inode->i_ctime.tv_sec = raw_inode->ctime; | ||
364 | inode->i_ctime.tv_nsec = 0; | ||
365 | inode->i_mtime.tv_nsec = 0; | ||
366 | inode->i_atime.tv_nsec = 0; | ||
367 | inode->i_blocks = (inode->i_size + 511) >> 9; | ||
368 | |||
369 | f = jffs_find_file(c, raw_inode->ino); | ||
370 | |||
371 | inode->i_private = (void *)f; | ||
372 | insert_inode_hash(inode); | ||
373 | |||
374 | return inode; | ||
375 | } | ||
376 | |||
377 | /* Get statistics of the file system. */ | ||
378 | static int | ||
379 | jffs_statfs(struct dentry *dentry, struct kstatfs *buf) | ||
380 | { | ||
381 | struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info; | ||
382 | struct jffs_fmcontrol *fmc; | ||
383 | |||
384 | lock_kernel(); | ||
385 | |||
386 | fmc = c->fmc; | ||
387 | |||
388 | D2(printk("jffs_statfs()\n")); | ||
389 | |||
390 | buf->f_type = JFFS_MAGIC_SB_BITMASK; | ||
391 | buf->f_bsize = PAGE_CACHE_SIZE; | ||
392 | buf->f_blocks = (fmc->flash_size / PAGE_CACHE_SIZE) | ||
393 | - (fmc->min_free_size / PAGE_CACHE_SIZE); | ||
394 | buf->f_bfree = (jffs_free_size1(fmc) + jffs_free_size2(fmc) + | ||
395 | fmc->dirty_size - fmc->min_free_size) | ||
396 | >> PAGE_CACHE_SHIFT; | ||
397 | buf->f_bavail = buf->f_bfree; | ||
398 | |||
399 | /* Find out how many files there are in the filesystem. */ | ||
400 | buf->f_files = jffs_foreach_file(c, jffs_file_count); | ||
401 | buf->f_ffree = buf->f_bfree; | ||
402 | /* buf->f_fsid = 0; */ | ||
403 | buf->f_namelen = JFFS_MAX_NAME_LEN; | ||
404 | |||
405 | unlock_kernel(); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | |||
411 | /* Rename a file. */ | ||
412 | static int | ||
413 | jffs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
414 | struct inode *new_dir, struct dentry *new_dentry) | ||
415 | { | ||
416 | struct jffs_raw_inode raw_inode; | ||
417 | struct jffs_control *c; | ||
418 | struct jffs_file *old_dir_f; | ||
419 | struct jffs_file *new_dir_f; | ||
420 | struct jffs_file *del_f; | ||
421 | struct jffs_file *f; | ||
422 | struct jffs_node *node; | ||
423 | struct inode *inode; | ||
424 | int result = 0; | ||
425 | __u32 rename_data = 0; | ||
426 | |||
427 | D2(printk("***jffs_rename()\n")); | ||
428 | |||
429 | D(printk("jffs_rename(): old_dir: 0x%p, old name: 0x%p, " | ||
430 | "new_dir: 0x%p, new name: 0x%p\n", | ||
431 | old_dir, old_dentry->d_name.name, | ||
432 | new_dir, new_dentry->d_name.name)); | ||
433 | |||
434 | lock_kernel(); | ||
435 | c = (struct jffs_control *)old_dir->i_sb->s_fs_info; | ||
436 | ASSERT(if (!c) { | ||
437 | printk(KERN_ERR "jffs_rename(): The old_dir inode " | ||
438 | "didn't have a reference to a jffs_file struct\n"); | ||
439 | unlock_kernel(); | ||
440 | return -EIO; | ||
441 | }); | ||
442 | |||
443 | result = -ENOTDIR; | ||
444 | if (!(old_dir_f = old_dir->i_private)) { | ||
445 | D(printk("jffs_rename(): Old dir invalid.\n")); | ||
446 | goto jffs_rename_end; | ||
447 | } | ||
448 | |||
449 | /* Try to find the file to move. */ | ||
450 | result = -ENOENT; | ||
451 | if (!(f = jffs_find_child(old_dir_f, old_dentry->d_name.name, | ||
452 | old_dentry->d_name.len))) { | ||
453 | goto jffs_rename_end; | ||
454 | } | ||
455 | |||
456 | /* Find the new directory. */ | ||
457 | result = -ENOTDIR; | ||
458 | if (!(new_dir_f = new_dir->i_private)) { | ||
459 | D(printk("jffs_rename(): New dir invalid.\n")); | ||
460 | goto jffs_rename_end; | ||
461 | } | ||
462 | D3(printk (KERN_NOTICE "rename(): down biglock\n")); | ||
463 | mutex_lock(&c->fmc->biglock); | ||
464 | /* Create a node and initialize as much as needed. */ | ||
465 | result = -ENOMEM; | ||
466 | if (!(node = jffs_alloc_node())) { | ||
467 | D(printk("jffs_rename(): Allocation failed: node == 0\n")); | ||
468 | goto jffs_rename_end; | ||
469 | } | ||
470 | node->data_offset = 0; | ||
471 | node->removed_size = 0; | ||
472 | |||
473 | /* Initialize the raw inode. */ | ||
474 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
475 | raw_inode.ino = f->ino; | ||
476 | raw_inode.pino = new_dir_f->ino; | ||
477 | /* raw_inode.version = f->highest_version + 1; */ | ||
478 | raw_inode.mode = f->mode; | ||
479 | raw_inode.uid = current->fsuid; | ||
480 | raw_inode.gid = current->fsgid; | ||
481 | #if 0 | ||
482 | raw_inode.uid = f->uid; | ||
483 | raw_inode.gid = f->gid; | ||
484 | #endif | ||
485 | raw_inode.atime = get_seconds(); | ||
486 | raw_inode.mtime = raw_inode.atime; | ||
487 | raw_inode.ctime = f->ctime; | ||
488 | raw_inode.offset = 0; | ||
489 | raw_inode.dsize = 0; | ||
490 | raw_inode.rsize = 0; | ||
491 | raw_inode.nsize = new_dentry->d_name.len; | ||
492 | raw_inode.nlink = f->nlink; | ||
493 | raw_inode.spare = 0; | ||
494 | raw_inode.rename = 0; | ||
495 | raw_inode.deleted = 0; | ||
496 | |||
497 | /* See if there already exists a file with the same name as | ||
498 | new_name. */ | ||
499 | if ((del_f = jffs_find_child(new_dir_f, new_dentry->d_name.name, | ||
500 | new_dentry->d_name.len))) { | ||
501 | raw_inode.rename = 1; | ||
502 | raw_inode.dsize = sizeof(__u32); | ||
503 | rename_data = del_f->ino; | ||
504 | } | ||
505 | |||
506 | /* Write the new node to the flash memory. */ | ||
507 | if ((result = jffs_write_node(c, node, &raw_inode, | ||
508 | new_dentry->d_name.name, | ||
509 | (unsigned char*)&rename_data, 0, f)) < 0) { | ||
510 | D(printk("jffs_rename(): Failed to write node to flash.\n")); | ||
511 | jffs_free_node(node); | ||
512 | goto jffs_rename_end; | ||
513 | } | ||
514 | raw_inode.dsize = 0; | ||
515 | |||
516 | if (raw_inode.rename) { | ||
517 | /* The file with the same name must be deleted. */ | ||
518 | //FIXME deadlock down(&c->fmc->gclock); | ||
519 | if ((result = jffs_remove(new_dir, new_dentry, | ||
520 | del_f->mode)) < 0) { | ||
521 | /* This is really bad. */ | ||
522 | printk(KERN_ERR "JFFS: An error occurred in " | ||
523 | "rename().\n"); | ||
524 | } | ||
525 | // up(&c->fmc->gclock); | ||
526 | } | ||
527 | |||
528 | if (old_dir_f != new_dir_f) { | ||
529 | /* Remove the file from its old position in the | ||
530 | filesystem tree. */ | ||
531 | jffs_unlink_file_from_tree(f); | ||
532 | } | ||
533 | |||
534 | /* Insert the new node into the file system. */ | ||
535 | if ((result = jffs_insert_node(c, f, &raw_inode, | ||
536 | new_dentry->d_name.name, node)) < 0) { | ||
537 | D(printk(KERN_ERR "jffs_rename(): jffs_insert_node() " | ||
538 | "failed!\n")); | ||
539 | } | ||
540 | |||
541 | if (old_dir_f != new_dir_f) { | ||
542 | /* Insert the file to its new position in the | ||
543 | file system. */ | ||
544 | jffs_insert_file_into_tree(f); | ||
545 | } | ||
546 | |||
547 | /* This is a kind of update of the inode we're about to make | ||
548 | here. This is what they do in ext2fs. Kind of. */ | ||
549 | if ((inode = iget(new_dir->i_sb, f->ino))) { | ||
550 | inode->i_ctime = CURRENT_TIME_SEC; | ||
551 | mark_inode_dirty(inode); | ||
552 | iput(inode); | ||
553 | } | ||
554 | |||
555 | jffs_rename_end: | ||
556 | D3(printk (KERN_NOTICE "rename(): up biglock\n")); | ||
557 | mutex_unlock(&c->fmc->biglock); | ||
558 | unlock_kernel(); | ||
559 | return result; | ||
560 | } /* jffs_rename() */ | ||
561 | |||
562 | |||
563 | /* Read the contents of a directory. Used by programs like `ls' | ||
564 | for instance. */ | ||
565 | static int | ||
566 | jffs_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
567 | { | ||
568 | struct jffs_file *f; | ||
569 | struct dentry *dentry = filp->f_path.dentry; | ||
570 | struct inode *inode = dentry->d_inode; | ||
571 | struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info; | ||
572 | int j; | ||
573 | int ddino; | ||
574 | lock_kernel(); | ||
575 | D3(printk (KERN_NOTICE "readdir(): down biglock\n")); | ||
576 | mutex_lock(&c->fmc->biglock); | ||
577 | |||
578 | D2(printk("jffs_readdir(): inode: 0x%p, filp: 0x%p\n", inode, filp)); | ||
579 | if (filp->f_pos == 0) { | ||
580 | D3(printk("jffs_readdir(): \".\" %lu\n", inode->i_ino)); | ||
581 | if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) { | ||
582 | D3(printk (KERN_NOTICE "readdir(): up biglock\n")); | ||
583 | mutex_unlock(&c->fmc->biglock); | ||
584 | unlock_kernel(); | ||
585 | return 0; | ||
586 | } | ||
587 | filp->f_pos = 1; | ||
588 | } | ||
589 | if (filp->f_pos == 1) { | ||
590 | if (inode->i_ino == JFFS_MIN_INO) { | ||
591 | ddino = JFFS_MIN_INO; | ||
592 | } | ||
593 | else { | ||
594 | ddino = ((struct jffs_file *) | ||
595 | inode->i_private)->pino; | ||
596 | } | ||
597 | D3(printk("jffs_readdir(): \"..\" %u\n", ddino)); | ||
598 | if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) { | ||
599 | D3(printk (KERN_NOTICE "readdir(): up biglock\n")); | ||
600 | mutex_unlock(&c->fmc->biglock); | ||
601 | unlock_kernel(); | ||
602 | return 0; | ||
603 | } | ||
604 | filp->f_pos++; | ||
605 | } | ||
606 | f = ((struct jffs_file *)inode->i_private)->children; | ||
607 | |||
608 | j = 2; | ||
609 | while(f && (f->deleted || j++ < filp->f_pos )) { | ||
610 | f = f->sibling_next; | ||
611 | } | ||
612 | |||
613 | while (f) { | ||
614 | D3(printk("jffs_readdir(): \"%s\" ino: %u\n", | ||
615 | (f->name ? f->name : ""), f->ino)); | ||
616 | if (filldir(dirent, f->name, f->nsize, | ||
617 | filp->f_pos , f->ino, DT_UNKNOWN) < 0) { | ||
618 | D3(printk (KERN_NOTICE "readdir(): up biglock\n")); | ||
619 | mutex_unlock(&c->fmc->biglock); | ||
620 | unlock_kernel(); | ||
621 | return 0; | ||
622 | } | ||
623 | filp->f_pos++; | ||
624 | do { | ||
625 | f = f->sibling_next; | ||
626 | } while(f && f->deleted); | ||
627 | } | ||
628 | D3(printk (KERN_NOTICE "readdir(): up biglock\n")); | ||
629 | mutex_unlock(&c->fmc->biglock); | ||
630 | unlock_kernel(); | ||
631 | return filp->f_pos; | ||
632 | } /* jffs_readdir() */ | ||
633 | |||
634 | |||
635 | /* Find a file in a directory. If the file exists, return its | ||
636 | corresponding dentry. */ | ||
637 | static struct dentry * | ||
638 | jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | ||
639 | { | ||
640 | struct jffs_file *d; | ||
641 | struct jffs_file *f; | ||
642 | struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info; | ||
643 | int len; | ||
644 | int r = 0; | ||
645 | const char *name; | ||
646 | struct inode *inode = NULL; | ||
647 | |||
648 | len = dentry->d_name.len; | ||
649 | name = dentry->d_name.name; | ||
650 | |||
651 | lock_kernel(); | ||
652 | |||
653 | D3({ | ||
654 | char *s = kmalloc(len + 1, GFP_KERNEL); | ||
655 | memcpy(s, name, len); | ||
656 | s[len] = '\0'; | ||
657 | printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s); | ||
658 | kfree(s); | ||
659 | }); | ||
660 | |||
661 | D3(printk (KERN_NOTICE "lookup(): down biglock\n")); | ||
662 | mutex_lock(&c->fmc->biglock); | ||
663 | |||
664 | r = -ENAMETOOLONG; | ||
665 | if (len > JFFS_MAX_NAME_LEN) { | ||
666 | goto jffs_lookup_end; | ||
667 | } | ||
668 | |||
669 | r = -EACCES; | ||
670 | if (!(d = (struct jffs_file *)dir->i_private)) { | ||
671 | D(printk("jffs_lookup(): No such inode! (%lu)\n", | ||
672 | dir->i_ino)); | ||
673 | goto jffs_lookup_end; | ||
674 | } | ||
675 | |||
676 | /* Get the corresponding inode to the file. */ | ||
677 | |||
678 | /* iget calls jffs_read_inode, so we need to drop the biglock | ||
679 | before calling iget. Unfortunately, the GC has a tendency | ||
680 | to sneak in here, because iget sometimes calls schedule (). | ||
681 | */ | ||
682 | |||
683 | if ((len == 1) && (name[0] == '.')) { | ||
684 | D3(printk (KERN_NOTICE "lookup(): up biglock\n")); | ||
685 | mutex_unlock(&c->fmc->biglock); | ||
686 | if (!(inode = iget(dir->i_sb, d->ino))) { | ||
687 | D(printk("jffs_lookup(): . iget() ==> NULL\n")); | ||
688 | goto jffs_lookup_end_no_biglock; | ||
689 | } | ||
690 | D3(printk (KERN_NOTICE "lookup(): down biglock\n")); | ||
691 | mutex_lock(&c->fmc->biglock); | ||
692 | } else if ((len == 2) && (name[0] == '.') && (name[1] == '.')) { | ||
693 | D3(printk (KERN_NOTICE "lookup(): up biglock\n")); | ||
694 | mutex_unlock(&c->fmc->biglock); | ||
695 | if (!(inode = iget(dir->i_sb, d->pino))) { | ||
696 | D(printk("jffs_lookup(): .. iget() ==> NULL\n")); | ||
697 | goto jffs_lookup_end_no_biglock; | ||
698 | } | ||
699 | D3(printk (KERN_NOTICE "lookup(): down biglock\n")); | ||
700 | mutex_lock(&c->fmc->biglock); | ||
701 | } else if ((f = jffs_find_child(d, name, len))) { | ||
702 | D3(printk (KERN_NOTICE "lookup(): up biglock\n")); | ||
703 | mutex_unlock(&c->fmc->biglock); | ||
704 | if (!(inode = iget(dir->i_sb, f->ino))) { | ||
705 | D(printk("jffs_lookup(): iget() ==> NULL\n")); | ||
706 | goto jffs_lookup_end_no_biglock; | ||
707 | } | ||
708 | D3(printk (KERN_NOTICE "lookup(): down biglock\n")); | ||
709 | mutex_lock(&c->fmc->biglock); | ||
710 | } else { | ||
711 | D3(printk("jffs_lookup(): Couldn't find the file. " | ||
712 | "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n", | ||
713 | f, name, d, d->ino)); | ||
714 | inode = NULL; | ||
715 | } | ||
716 | |||
717 | d_add(dentry, inode); | ||
718 | D3(printk (KERN_NOTICE "lookup(): up biglock\n")); | ||
719 | mutex_unlock(&c->fmc->biglock); | ||
720 | unlock_kernel(); | ||
721 | return NULL; | ||
722 | |||
723 | jffs_lookup_end: | ||
724 | D3(printk (KERN_NOTICE "lookup(): up biglock\n")); | ||
725 | mutex_unlock(&c->fmc->biglock); | ||
726 | |||
727 | jffs_lookup_end_no_biglock: | ||
728 | unlock_kernel(); | ||
729 | return ERR_PTR(r); | ||
730 | } /* jffs_lookup() */ | ||
731 | |||
732 | |||
733 | /* Try to read a page of data from a file. */ | ||
734 | static int | ||
735 | jffs_do_readpage_nolock(struct file *file, struct page *page) | ||
736 | { | ||
737 | void *buf; | ||
738 | unsigned long read_len; | ||
739 | int result; | ||
740 | struct inode *inode = (struct inode*)page->mapping->host; | ||
741 | struct jffs_file *f = (struct jffs_file *)inode->i_private; | ||
742 | struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info; | ||
743 | int r; | ||
744 | loff_t offset; | ||
745 | |||
746 | D2(printk("***jffs_readpage(): file = \"%s\", page->index = %lu\n", | ||
747 | (f->name ? f->name : ""), (long)page->index)); | ||
748 | |||
749 | get_page(page); | ||
750 | /* Don't SetPageLocked(page), should be locked already */ | ||
751 | ClearPageUptodate(page); | ||
752 | ClearPageError(page); | ||
753 | |||
754 | D3(printk (KERN_NOTICE "readpage(): down biglock\n")); | ||
755 | mutex_lock(&c->fmc->biglock); | ||
756 | |||
757 | read_len = 0; | ||
758 | result = 0; | ||
759 | offset = page_offset(page); | ||
760 | |||
761 | kmap(page); | ||
762 | buf = page_address(page); | ||
763 | if (offset < inode->i_size) { | ||
764 | read_len = min_t(long, inode->i_size - offset, PAGE_SIZE); | ||
765 | r = jffs_read_data(f, buf, offset, read_len); | ||
766 | if (r != read_len) { | ||
767 | result = -EIO; | ||
768 | D( | ||
769 | printk("***jffs_readpage(): Read error! " | ||
770 | "Wanted to read %lu bytes but only " | ||
771 | "read %d bytes.\n", read_len, r); | ||
772 | ); | ||
773 | } | ||
774 | |||
775 | } | ||
776 | |||
777 | /* This handles the case of partial or no read in above */ | ||
778 | if(read_len < PAGE_SIZE) | ||
779 | memset(buf + read_len, 0, PAGE_SIZE - read_len); | ||
780 | flush_dcache_page(page); | ||
781 | kunmap(page); | ||
782 | |||
783 | D3(printk (KERN_NOTICE "readpage(): up biglock\n")); | ||
784 | mutex_unlock(&c->fmc->biglock); | ||
785 | |||
786 | if (result) { | ||
787 | SetPageError(page); | ||
788 | }else { | ||
789 | SetPageUptodate(page); | ||
790 | } | ||
791 | |||
792 | page_cache_release(page); | ||
793 | |||
794 | D3(printk("jffs_readpage(): Leaving...\n")); | ||
795 | |||
796 | return result; | ||
797 | } /* jffs_do_readpage_nolock() */ | ||
798 | |||
799 | static int jffs_readpage(struct file *file, struct page *page) | ||
800 | { | ||
801 | int ret = jffs_do_readpage_nolock(file, page); | ||
802 | unlock_page(page); | ||
803 | return ret; | ||
804 | } | ||
805 | |||
806 | /* Create a new directory. */ | ||
807 | static int | ||
808 | jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
809 | { | ||
810 | struct jffs_raw_inode raw_inode; | ||
811 | struct jffs_control *c; | ||
812 | struct jffs_node *node; | ||
813 | struct jffs_file *dir_f; | ||
814 | struct inode *inode; | ||
815 | int dir_mode; | ||
816 | int result = 0; | ||
817 | int err; | ||
818 | |||
819 | D1({ | ||
820 | int len = dentry->d_name.len; | ||
821 | char *_name = kmalloc(len + 1, GFP_KERNEL); | ||
822 | memcpy(_name, dentry->d_name.name, len); | ||
823 | _name[len] = '\0'; | ||
824 | printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", " | ||
825 | "len = %d, mode = 0x%08x\n", dir, _name, len, mode); | ||
826 | kfree(_name); | ||
827 | }); | ||
828 | |||
829 | lock_kernel(); | ||
830 | dir_f = dir->i_private; | ||
831 | |||
832 | ASSERT(if (!dir_f) { | ||
833 | printk(KERN_ERR "jffs_mkdir(): No reference to a " | ||
834 | "jffs_file struct in inode.\n"); | ||
835 | unlock_kernel(); | ||
836 | return -EIO; | ||
837 | }); | ||
838 | |||
839 | c = dir_f->c; | ||
840 | D3(printk (KERN_NOTICE "mkdir(): down biglock\n")); | ||
841 | mutex_lock(&c->fmc->biglock); | ||
842 | |||
843 | dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) | ||
844 | & ~current->fs->umask); | ||
845 | if (dir->i_mode & S_ISGID) { | ||
846 | dir_mode |= S_ISGID; | ||
847 | } | ||
848 | |||
849 | /* Create a node and initialize it as much as needed. */ | ||
850 | if (!(node = jffs_alloc_node())) { | ||
851 | D(printk("jffs_mkdir(): Allocation failed: node == 0\n")); | ||
852 | result = -ENOMEM; | ||
853 | goto jffs_mkdir_end; | ||
854 | } | ||
855 | node->data_offset = 0; | ||
856 | node->removed_size = 0; | ||
857 | |||
858 | /* Initialize the raw inode. */ | ||
859 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
860 | raw_inode.ino = c->next_ino++; | ||
861 | raw_inode.pino = dir_f->ino; | ||
862 | raw_inode.version = 1; | ||
863 | raw_inode.mode = dir_mode; | ||
864 | raw_inode.uid = current->fsuid; | ||
865 | raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; | ||
866 | /* raw_inode.gid = current->fsgid; */ | ||
867 | raw_inode.atime = get_seconds(); | ||
868 | raw_inode.mtime = raw_inode.atime; | ||
869 | raw_inode.ctime = raw_inode.atime; | ||
870 | raw_inode.offset = 0; | ||
871 | raw_inode.dsize = 0; | ||
872 | raw_inode.rsize = 0; | ||
873 | raw_inode.nsize = dentry->d_name.len; | ||
874 | raw_inode.nlink = 1; | ||
875 | raw_inode.spare = 0; | ||
876 | raw_inode.rename = 0; | ||
877 | raw_inode.deleted = 0; | ||
878 | |||
879 | /* Write the new node to the flash. */ | ||
880 | if ((result = jffs_write_node(c, node, &raw_inode, | ||
881 | dentry->d_name.name, NULL, 0, NULL)) < 0) { | ||
882 | D(printk("jffs_mkdir(): jffs_write_node() failed.\n")); | ||
883 | jffs_free_node(node); | ||
884 | goto jffs_mkdir_end; | ||
885 | } | ||
886 | |||
887 | /* Insert the new node into the file system. */ | ||
888 | if ((result = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name, | ||
889 | node)) < 0) { | ||
890 | goto jffs_mkdir_end; | ||
891 | } | ||
892 | |||
893 | inode = jffs_new_inode(dir, &raw_inode, &err); | ||
894 | if (inode == NULL) { | ||
895 | result = err; | ||
896 | goto jffs_mkdir_end; | ||
897 | } | ||
898 | |||
899 | inode->i_op = &jffs_dir_inode_operations; | ||
900 | inode->i_fop = &jffs_dir_operations; | ||
901 | |||
902 | mark_inode_dirty(dir); | ||
903 | d_instantiate(dentry, inode); | ||
904 | |||
905 | result = 0; | ||
906 | jffs_mkdir_end: | ||
907 | D3(printk (KERN_NOTICE "mkdir(): up biglock\n")); | ||
908 | mutex_unlock(&c->fmc->biglock); | ||
909 | unlock_kernel(); | ||
910 | return result; | ||
911 | } /* jffs_mkdir() */ | ||
912 | |||
913 | |||
914 | /* Remove a directory. */ | ||
915 | static int | ||
916 | jffs_rmdir(struct inode *dir, struct dentry *dentry) | ||
917 | { | ||
918 | struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info; | ||
919 | int ret; | ||
920 | D3(printk("***jffs_rmdir()\n")); | ||
921 | D3(printk (KERN_NOTICE "rmdir(): down biglock\n")); | ||
922 | lock_kernel(); | ||
923 | mutex_lock(&c->fmc->biglock); | ||
924 | ret = jffs_remove(dir, dentry, S_IFDIR); | ||
925 | D3(printk (KERN_NOTICE "rmdir(): up biglock\n")); | ||
926 | mutex_unlock(&c->fmc->biglock); | ||
927 | unlock_kernel(); | ||
928 | return ret; | ||
929 | } | ||
930 | |||
931 | |||
932 | /* Remove any kind of file except for directories. */ | ||
933 | static int | ||
934 | jffs_unlink(struct inode *dir, struct dentry *dentry) | ||
935 | { | ||
936 | struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info; | ||
937 | int ret; | ||
938 | |||
939 | lock_kernel(); | ||
940 | D3(printk("***jffs_unlink()\n")); | ||
941 | D3(printk (KERN_NOTICE "unlink(): down biglock\n")); | ||
942 | mutex_lock(&c->fmc->biglock); | ||
943 | ret = jffs_remove(dir, dentry, 0); | ||
944 | D3(printk (KERN_NOTICE "unlink(): up biglock\n")); | ||
945 | mutex_unlock(&c->fmc->biglock); | ||
946 | unlock_kernel(); | ||
947 | return ret; | ||
948 | } | ||
949 | |||
950 | |||
951 | /* Remove a JFFS entry, i.e. plain files, directories, etc. Here we | ||
952 | shouldn't test for free space on the device. */ | ||
953 | static int | ||
954 | jffs_remove(struct inode *dir, struct dentry *dentry, int type) | ||
955 | { | ||
956 | struct jffs_raw_inode raw_inode; | ||
957 | struct jffs_control *c; | ||
958 | struct jffs_file *dir_f; /* The file-to-remove's parent. */ | ||
959 | struct jffs_file *del_f; /* The file to remove. */ | ||
960 | struct jffs_node *del_node; | ||
961 | struct inode *inode = NULL; | ||
962 | int result = 0; | ||
963 | |||
964 | D1({ | ||
965 | int len = dentry->d_name.len; | ||
966 | const char *name = dentry->d_name.name; | ||
967 | char *_name = kmalloc(len + 1, GFP_KERNEL); | ||
968 | memcpy(_name, name, len); | ||
969 | _name[len] = '\0'; | ||
970 | printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino); | ||
971 | kfree(_name); | ||
972 | }); | ||
973 | |||
974 | dir_f = dir->i_private; | ||
975 | c = dir_f->c; | ||
976 | |||
977 | result = -ENOENT; | ||
978 | if (!(del_f = jffs_find_child(dir_f, dentry->d_name.name, | ||
979 | dentry->d_name.len))) { | ||
980 | D(printk("jffs_remove(): jffs_find_child() failed.\n")); | ||
981 | goto jffs_remove_end; | ||
982 | } | ||
983 | |||
984 | if (S_ISDIR(type)) { | ||
985 | struct jffs_file *child = del_f->children; | ||
986 | while(child) { | ||
987 | if( !child->deleted ) { | ||
988 | result = -ENOTEMPTY; | ||
989 | goto jffs_remove_end; | ||
990 | } | ||
991 | child = child->sibling_next; | ||
992 | } | ||
993 | } | ||
994 | else if (S_ISDIR(del_f->mode)) { | ||
995 | D(printk("jffs_remove(): node is a directory " | ||
996 | "but it shouldn't be.\n")); | ||
997 | result = -EPERM; | ||
998 | goto jffs_remove_end; | ||
999 | } | ||
1000 | |||
1001 | inode = dentry->d_inode; | ||
1002 | |||
1003 | result = -EIO; | ||
1004 | if (del_f->ino != inode->i_ino) | ||
1005 | goto jffs_remove_end; | ||
1006 | |||
1007 | if (!inode->i_nlink) { | ||
1008 | printk("Deleting nonexistent file inode: %lu, nlink: %d\n", | ||
1009 | inode->i_ino, inode->i_nlink); | ||
1010 | inode->i_nlink=1; | ||
1011 | } | ||
1012 | |||
1013 | /* Create a node for the deletion. */ | ||
1014 | result = -ENOMEM; | ||
1015 | if (!(del_node = jffs_alloc_node())) { | ||
1016 | D(printk("jffs_remove(): Allocation failed!\n")); | ||
1017 | goto jffs_remove_end; | ||
1018 | } | ||
1019 | del_node->data_offset = 0; | ||
1020 | del_node->removed_size = 0; | ||
1021 | |||
1022 | /* Initialize the raw inode. */ | ||
1023 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
1024 | raw_inode.ino = del_f->ino; | ||
1025 | raw_inode.pino = del_f->pino; | ||
1026 | /* raw_inode.version = del_f->highest_version + 1; */ | ||
1027 | raw_inode.mode = del_f->mode; | ||
1028 | raw_inode.uid = current->fsuid; | ||
1029 | raw_inode.gid = current->fsgid; | ||
1030 | raw_inode.atime = get_seconds(); | ||
1031 | raw_inode.mtime = del_f->mtime; | ||
1032 | raw_inode.ctime = raw_inode.atime; | ||
1033 | raw_inode.offset = 0; | ||
1034 | raw_inode.dsize = 0; | ||
1035 | raw_inode.rsize = 0; | ||
1036 | raw_inode.nsize = 0; | ||
1037 | raw_inode.nlink = del_f->nlink; | ||
1038 | raw_inode.spare = 0; | ||
1039 | raw_inode.rename = 0; | ||
1040 | raw_inode.deleted = 1; | ||
1041 | |||
1042 | /* Write the new node to the flash memory. */ | ||
1043 | if (jffs_write_node(c, del_node, &raw_inode, NULL, NULL, 1, del_f) < 0) { | ||
1044 | jffs_free_node(del_node); | ||
1045 | result = -EIO; | ||
1046 | goto jffs_remove_end; | ||
1047 | } | ||
1048 | |||
1049 | /* Update the file. This operation will make the file disappear | ||
1050 | from the in-memory file system structures. */ | ||
1051 | jffs_insert_node(c, del_f, &raw_inode, NULL, del_node); | ||
1052 | |||
1053 | dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; | ||
1054 | mark_inode_dirty(dir); | ||
1055 | inode->i_ctime = dir->i_ctime; | ||
1056 | inode_dec_link_count(inode); | ||
1057 | |||
1058 | d_delete(dentry); /* This also frees the inode */ | ||
1059 | |||
1060 | result = 0; | ||
1061 | jffs_remove_end: | ||
1062 | return result; | ||
1063 | } /* jffs_remove() */ | ||
1064 | |||
1065 | |||
1066 | static int | ||
1067 | jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | ||
1068 | { | ||
1069 | struct jffs_raw_inode raw_inode; | ||
1070 | struct jffs_file *dir_f; | ||
1071 | struct jffs_node *node = NULL; | ||
1072 | struct jffs_control *c; | ||
1073 | struct inode *inode; | ||
1074 | int result = 0; | ||
1075 | u16 data = old_encode_dev(rdev); | ||
1076 | int err; | ||
1077 | |||
1078 | D1(printk("***jffs_mknod()\n")); | ||
1079 | |||
1080 | if (!old_valid_dev(rdev)) | ||
1081 | return -EINVAL; | ||
1082 | lock_kernel(); | ||
1083 | dir_f = dir->i_private; | ||
1084 | c = dir_f->c; | ||
1085 | |||
1086 | D3(printk (KERN_NOTICE "mknod(): down biglock\n")); | ||
1087 | mutex_lock(&c->fmc->biglock); | ||
1088 | |||
1089 | /* Create and initialize a new node. */ | ||
1090 | if (!(node = jffs_alloc_node())) { | ||
1091 | D(printk("jffs_mknod(): Allocation failed!\n")); | ||
1092 | result = -ENOMEM; | ||
1093 | goto jffs_mknod_err; | ||
1094 | } | ||
1095 | node->data_offset = 0; | ||
1096 | node->removed_size = 0; | ||
1097 | |||
1098 | /* Initialize the raw inode. */ | ||
1099 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
1100 | raw_inode.ino = c->next_ino++; | ||
1101 | raw_inode.pino = dir_f->ino; | ||
1102 | raw_inode.version = 1; | ||
1103 | raw_inode.mode = mode; | ||
1104 | raw_inode.uid = current->fsuid; | ||
1105 | raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; | ||
1106 | /* raw_inode.gid = current->fsgid; */ | ||
1107 | raw_inode.atime = get_seconds(); | ||
1108 | raw_inode.mtime = raw_inode.atime; | ||
1109 | raw_inode.ctime = raw_inode.atime; | ||
1110 | raw_inode.offset = 0; | ||
1111 | raw_inode.dsize = 2; | ||
1112 | raw_inode.rsize = 0; | ||
1113 | raw_inode.nsize = dentry->d_name.len; | ||
1114 | raw_inode.nlink = 1; | ||
1115 | raw_inode.spare = 0; | ||
1116 | raw_inode.rename = 0; | ||
1117 | raw_inode.deleted = 0; | ||
1118 | |||
1119 | /* Write the new node to the flash. */ | ||
1120 | if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name, | ||
1121 | (unsigned char *)&data, 0, NULL)) < 0) { | ||
1122 | D(printk("jffs_mknod(): jffs_write_node() failed.\n")); | ||
1123 | result = err; | ||
1124 | goto jffs_mknod_err; | ||
1125 | } | ||
1126 | |||
1127 | /* Insert the new node into the file system. */ | ||
1128 | if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name, | ||
1129 | node)) < 0) { | ||
1130 | result = err; | ||
1131 | goto jffs_mknod_end; | ||
1132 | } | ||
1133 | |||
1134 | inode = jffs_new_inode(dir, &raw_inode, &err); | ||
1135 | if (inode == NULL) { | ||
1136 | result = err; | ||
1137 | goto jffs_mknod_end; | ||
1138 | } | ||
1139 | |||
1140 | init_special_inode(inode, mode, rdev); | ||
1141 | |||
1142 | d_instantiate(dentry, inode); | ||
1143 | |||
1144 | goto jffs_mknod_end; | ||
1145 | |||
1146 | jffs_mknod_err: | ||
1147 | if (node) { | ||
1148 | jffs_free_node(node); | ||
1149 | } | ||
1150 | |||
1151 | jffs_mknod_end: | ||
1152 | D3(printk (KERN_NOTICE "mknod(): up biglock\n")); | ||
1153 | mutex_unlock(&c->fmc->biglock); | ||
1154 | unlock_kernel(); | ||
1155 | return result; | ||
1156 | } /* jffs_mknod() */ | ||
1157 | |||
1158 | |||
1159 | static int | ||
1160 | jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | ||
1161 | { | ||
1162 | struct jffs_raw_inode raw_inode; | ||
1163 | struct jffs_control *c; | ||
1164 | struct jffs_file *dir_f; | ||
1165 | struct jffs_node *node; | ||
1166 | struct inode *inode; | ||
1167 | |||
1168 | int symname_len = strlen(symname); | ||
1169 | int err; | ||
1170 | |||
1171 | lock_kernel(); | ||
1172 | D1({ | ||
1173 | int len = dentry->d_name.len; | ||
1174 | char *_name = kmalloc(len + 1, GFP_KERNEL); | ||
1175 | char *_symname = kmalloc(symname_len + 1, GFP_KERNEL); | ||
1176 | memcpy(_name, dentry->d_name.name, len); | ||
1177 | _name[len] = '\0'; | ||
1178 | memcpy(_symname, symname, symname_len); | ||
1179 | _symname[symname_len] = '\0'; | ||
1180 | printk("***jffs_symlink(): dir = 0x%p, " | ||
1181 | "dentry->dname.name = \"%s\", " | ||
1182 | "symname = \"%s\"\n", dir, _name, _symname); | ||
1183 | kfree(_name); | ||
1184 | kfree(_symname); | ||
1185 | }); | ||
1186 | |||
1187 | dir_f = dir->i_private; | ||
1188 | ASSERT(if (!dir_f) { | ||
1189 | printk(KERN_ERR "jffs_symlink(): No reference to a " | ||
1190 | "jffs_file struct in inode.\n"); | ||
1191 | unlock_kernel(); | ||
1192 | return -EIO; | ||
1193 | }); | ||
1194 | |||
1195 | c = dir_f->c; | ||
1196 | |||
1197 | /* Create a node and initialize it as much as needed. */ | ||
1198 | if (!(node = jffs_alloc_node())) { | ||
1199 | D(printk("jffs_symlink(): Allocation failed: node = NULL\n")); | ||
1200 | unlock_kernel(); | ||
1201 | return -ENOMEM; | ||
1202 | } | ||
1203 | D3(printk (KERN_NOTICE "symlink(): down biglock\n")); | ||
1204 | mutex_lock(&c->fmc->biglock); | ||
1205 | |||
1206 | node->data_offset = 0; | ||
1207 | node->removed_size = 0; | ||
1208 | |||
1209 | /* Initialize the raw inode. */ | ||
1210 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
1211 | raw_inode.ino = c->next_ino++; | ||
1212 | raw_inode.pino = dir_f->ino; | ||
1213 | raw_inode.version = 1; | ||
1214 | raw_inode.mode = S_IFLNK | S_IRWXUGO; | ||
1215 | raw_inode.uid = current->fsuid; | ||
1216 | raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; | ||
1217 | raw_inode.atime = get_seconds(); | ||
1218 | raw_inode.mtime = raw_inode.atime; | ||
1219 | raw_inode.ctime = raw_inode.atime; | ||
1220 | raw_inode.offset = 0; | ||
1221 | raw_inode.dsize = symname_len; | ||
1222 | raw_inode.rsize = 0; | ||
1223 | raw_inode.nsize = dentry->d_name.len; | ||
1224 | raw_inode.nlink = 1; | ||
1225 | raw_inode.spare = 0; | ||
1226 | raw_inode.rename = 0; | ||
1227 | raw_inode.deleted = 0; | ||
1228 | |||
1229 | /* Write the new node to the flash. */ | ||
1230 | if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name, | ||
1231 | (const unsigned char *)symname, 0, NULL)) < 0) { | ||
1232 | D(printk("jffs_symlink(): jffs_write_node() failed.\n")); | ||
1233 | jffs_free_node(node); | ||
1234 | goto jffs_symlink_end; | ||
1235 | } | ||
1236 | |||
1237 | /* Insert the new node into the file system. */ | ||
1238 | if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name, | ||
1239 | node)) < 0) { | ||
1240 | goto jffs_symlink_end; | ||
1241 | } | ||
1242 | |||
1243 | inode = jffs_new_inode(dir, &raw_inode, &err); | ||
1244 | if (inode == NULL) { | ||
1245 | goto jffs_symlink_end; | ||
1246 | } | ||
1247 | err = 0; | ||
1248 | inode->i_op = &page_symlink_inode_operations; | ||
1249 | inode->i_mapping->a_ops = &jffs_address_operations; | ||
1250 | |||
1251 | d_instantiate(dentry, inode); | ||
1252 | jffs_symlink_end: | ||
1253 | D3(printk (KERN_NOTICE "symlink(): up biglock\n")); | ||
1254 | mutex_unlock(&c->fmc->biglock); | ||
1255 | unlock_kernel(); | ||
1256 | return err; | ||
1257 | } /* jffs_symlink() */ | ||
1258 | |||
1259 | |||
1260 | /* Create an inode inside a JFFS directory (dir) and return it. | ||
1261 | * | ||
1262 | * By the time this is called, we already have created | ||
1263 | * the directory cache entry for the new file, but it | ||
1264 | * is so far negative - it has no inode. | ||
1265 | * | ||
1266 | * If the create succeeds, we fill in the inode information | ||
1267 | * with d_instantiate(). | ||
1268 | */ | ||
1269 | static int | ||
1270 | jffs_create(struct inode *dir, struct dentry *dentry, int mode, | ||
1271 | struct nameidata *nd) | ||
1272 | { | ||
1273 | struct jffs_raw_inode raw_inode; | ||
1274 | struct jffs_control *c; | ||
1275 | struct jffs_node *node; | ||
1276 | struct jffs_file *dir_f; /* JFFS representation of the directory. */ | ||
1277 | struct inode *inode; | ||
1278 | int err; | ||
1279 | |||
1280 | lock_kernel(); | ||
1281 | D1({ | ||
1282 | int len = dentry->d_name.len; | ||
1283 | char *s = kmalloc(len + 1, GFP_KERNEL); | ||
1284 | memcpy(s, dentry->d_name.name, len); | ||
1285 | s[len] = '\0'; | ||
1286 | printk("jffs_create(): dir: 0x%p, name: \"%s\"\n", dir, s); | ||
1287 | kfree(s); | ||
1288 | }); | ||
1289 | |||
1290 | dir_f = dir->i_private; | ||
1291 | ASSERT(if (!dir_f) { | ||
1292 | printk(KERN_ERR "jffs_create(): No reference to a " | ||
1293 | "jffs_file struct in inode.\n"); | ||
1294 | unlock_kernel(); | ||
1295 | return -EIO; | ||
1296 | }); | ||
1297 | |||
1298 | c = dir_f->c; | ||
1299 | |||
1300 | /* Create a node and initialize as much as needed. */ | ||
1301 | if (!(node = jffs_alloc_node())) { | ||
1302 | D(printk("jffs_create(): Allocation failed: node == 0\n")); | ||
1303 | unlock_kernel(); | ||
1304 | return -ENOMEM; | ||
1305 | } | ||
1306 | D3(printk (KERN_NOTICE "create(): down biglock\n")); | ||
1307 | mutex_lock(&c->fmc->biglock); | ||
1308 | |||
1309 | node->data_offset = 0; | ||
1310 | node->removed_size = 0; | ||
1311 | |||
1312 | /* Initialize the raw inode. */ | ||
1313 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
1314 | raw_inode.ino = c->next_ino++; | ||
1315 | raw_inode.pino = dir_f->ino; | ||
1316 | raw_inode.version = 1; | ||
1317 | raw_inode.mode = mode; | ||
1318 | raw_inode.uid = current->fsuid; | ||
1319 | raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; | ||
1320 | raw_inode.atime = get_seconds(); | ||
1321 | raw_inode.mtime = raw_inode.atime; | ||
1322 | raw_inode.ctime = raw_inode.atime; | ||
1323 | raw_inode.offset = 0; | ||
1324 | raw_inode.dsize = 0; | ||
1325 | raw_inode.rsize = 0; | ||
1326 | raw_inode.nsize = dentry->d_name.len; | ||
1327 | raw_inode.nlink = 1; | ||
1328 | raw_inode.spare = 0; | ||
1329 | raw_inode.rename = 0; | ||
1330 | raw_inode.deleted = 0; | ||
1331 | |||
1332 | /* Write the new node to the flash. */ | ||
1333 | if ((err = jffs_write_node(c, node, &raw_inode, | ||
1334 | dentry->d_name.name, NULL, 0, NULL)) < 0) { | ||
1335 | D(printk("jffs_create(): jffs_write_node() failed.\n")); | ||
1336 | jffs_free_node(node); | ||
1337 | goto jffs_create_end; | ||
1338 | } | ||
1339 | |||
1340 | /* Insert the new node into the file system. */ | ||
1341 | if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name, | ||
1342 | node)) < 0) { | ||
1343 | goto jffs_create_end; | ||
1344 | } | ||
1345 | |||
1346 | /* Initialize an inode. */ | ||
1347 | inode = jffs_new_inode(dir, &raw_inode, &err); | ||
1348 | if (inode == NULL) { | ||
1349 | goto jffs_create_end; | ||
1350 | } | ||
1351 | err = 0; | ||
1352 | inode->i_op = &jffs_file_inode_operations; | ||
1353 | inode->i_fop = &jffs_file_operations; | ||
1354 | inode->i_mapping->a_ops = &jffs_address_operations; | ||
1355 | inode->i_mapping->nrpages = 0; | ||
1356 | |||
1357 | d_instantiate(dentry, inode); | ||
1358 | jffs_create_end: | ||
1359 | D3(printk (KERN_NOTICE "create(): up biglock\n")); | ||
1360 | mutex_unlock(&c->fmc->biglock); | ||
1361 | unlock_kernel(); | ||
1362 | return err; | ||
1363 | } /* jffs_create() */ | ||
1364 | |||
1365 | |||
1366 | /* Write, append or rewrite data to an existing file. */ | ||
1367 | static ssize_t | ||
1368 | jffs_file_write(struct file *filp, const char *buf, size_t count, | ||
1369 | loff_t *ppos) | ||
1370 | { | ||
1371 | struct jffs_raw_inode raw_inode; | ||
1372 | struct jffs_control *c; | ||
1373 | struct jffs_file *f; | ||
1374 | struct jffs_node *node; | ||
1375 | struct dentry *dentry = filp->f_path.dentry; | ||
1376 | struct inode *inode = dentry->d_inode; | ||
1377 | int recoverable = 0; | ||
1378 | size_t written = 0; | ||
1379 | __u32 thiscount = count; | ||
1380 | loff_t pos = *ppos; | ||
1381 | int err; | ||
1382 | |||
1383 | inode = filp->f_path.dentry->d_inode; | ||
1384 | |||
1385 | D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), " | ||
1386 | "filp: 0x%p, buf: 0x%p, count: %d\n", | ||
1387 | inode, inode->i_ino, filp, buf, count)); | ||
1388 | |||
1389 | #if 0 | ||
1390 | if (inode->i_sb->s_flags & MS_RDONLY) { | ||
1391 | D(printk("jffs_file_write(): MS_RDONLY\n")); | ||
1392 | err = -EROFS; | ||
1393 | goto out_isem; | ||
1394 | } | ||
1395 | #endif | ||
1396 | err = -EINVAL; | ||
1397 | |||
1398 | if (!S_ISREG(inode->i_mode)) { | ||
1399 | D(printk("jffs_file_write(): inode->i_mode == 0x%08x\n", | ||
1400 | inode->i_mode)); | ||
1401 | goto out_isem; | ||
1402 | } | ||
1403 | |||
1404 | if (!(f = inode->i_private)) { | ||
1405 | D(printk("jffs_file_write(): inode->i_private = 0x%p\n", | ||
1406 | inode->i_private)); | ||
1407 | goto out_isem; | ||
1408 | } | ||
1409 | |||
1410 | c = f->c; | ||
1411 | |||
1412 | /* | ||
1413 | * This will never trigger with sane page sizes. leave it in | ||
1414 | * anyway, since I'm thinking about how to merge larger writes | ||
1415 | * (the current idea is to poke a thread that does the actual | ||
1416 | * I/O and starts by doing a mutex_lock(&inode->i_mutex). then we | ||
1417 | * would need to get the page cache pages and have a list of | ||
1418 | * I/O requests and do write-merging here. | ||
1419 | * -- prumpf | ||
1420 | */ | ||
1421 | thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count); | ||
1422 | |||
1423 | D3(printk (KERN_NOTICE "file_write(): down biglock\n")); | ||
1424 | mutex_lock(&c->fmc->biglock); | ||
1425 | |||
1426 | /* Urgh. POSIX says we can do short writes if we feel like it. | ||
1427 | * In practice, we can't. Nothing will cope. So we loop until | ||
1428 | * we're done. | ||
1429 | * | ||
1430 | * <_Anarchy_> posix and reality are not interconnected on this issue | ||
1431 | */ | ||
1432 | while (count) { | ||
1433 | /* Things are going to be written so we could allocate and | ||
1434 | initialize the necessary data structures now. */ | ||
1435 | if (!(node = jffs_alloc_node())) { | ||
1436 | D(printk("jffs_file_write(): node == 0\n")); | ||
1437 | err = -ENOMEM; | ||
1438 | goto out; | ||
1439 | } | ||
1440 | |||
1441 | node->data_offset = pos; | ||
1442 | node->removed_size = 0; | ||
1443 | |||
1444 | /* Initialize the raw inode. */ | ||
1445 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
1446 | raw_inode.ino = f->ino; | ||
1447 | raw_inode.pino = f->pino; | ||
1448 | |||
1449 | raw_inode.mode = f->mode; | ||
1450 | |||
1451 | raw_inode.uid = f->uid; | ||
1452 | raw_inode.gid = f->gid; | ||
1453 | raw_inode.atime = get_seconds(); | ||
1454 | raw_inode.mtime = raw_inode.atime; | ||
1455 | raw_inode.ctime = f->ctime; | ||
1456 | raw_inode.offset = pos; | ||
1457 | raw_inode.dsize = thiscount; | ||
1458 | raw_inode.rsize = 0; | ||
1459 | raw_inode.nsize = f->nsize; | ||
1460 | raw_inode.nlink = f->nlink; | ||
1461 | raw_inode.spare = 0; | ||
1462 | raw_inode.rename = 0; | ||
1463 | raw_inode.deleted = 0; | ||
1464 | |||
1465 | if (pos < f->size) { | ||
1466 | node->removed_size = raw_inode.rsize = min(thiscount, (__u32)(f->size - pos)); | ||
1467 | |||
1468 | /* If this node is going entirely over the top of old data, | ||
1469 | we can allow it to go into the reserved space, because | ||
1470 | we know that GC can reclaim the space later. | ||
1471 | */ | ||
1472 | if (pos + thiscount < f->size) { | ||
1473 | /* If all the data we're overwriting are _real_, | ||
1474 | not just holes, then: | ||
1475 | recoverable = 1; | ||
1476 | */ | ||
1477 | } | ||
1478 | } | ||
1479 | |||
1480 | /* Write the new node to the flash. */ | ||
1481 | /* NOTE: We would be quite happy if jffs_write_node() wrote a | ||
1482 | smaller node than we were expecting. There's no need for it | ||
1483 | to waste the space at the end of the flash just because it's | ||
1484 | a little smaller than what we asked for. But that's a whole | ||
1485 | new can of worms which I'm not going to open this week. | ||
1486 | -- dwmw2. | ||
1487 | */ | ||
1488 | if ((err = jffs_write_node(c, node, &raw_inode, f->name, | ||
1489 | (const unsigned char *)buf, | ||
1490 | recoverable, f)) < 0) { | ||
1491 | D(printk("jffs_file_write(): jffs_write_node() failed.\n")); | ||
1492 | jffs_free_node(node); | ||
1493 | goto out; | ||
1494 | } | ||
1495 | |||
1496 | written += err; | ||
1497 | buf += err; | ||
1498 | count -= err; | ||
1499 | pos += err; | ||
1500 | |||
1501 | /* Insert the new node into the file system. */ | ||
1502 | if ((err = jffs_insert_node(c, f, &raw_inode, NULL, node)) < 0) { | ||
1503 | goto out; | ||
1504 | } | ||
1505 | |||
1506 | D3(printk("jffs_file_write(): new f_pos %ld.\n", (long)pos)); | ||
1507 | |||
1508 | thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count); | ||
1509 | } | ||
1510 | out: | ||
1511 | D3(printk (KERN_NOTICE "file_write(): up biglock\n")); | ||
1512 | mutex_unlock(&c->fmc->biglock); | ||
1513 | |||
1514 | /* Fix things in the real inode. */ | ||
1515 | if (pos > inode->i_size) { | ||
1516 | inode->i_size = pos; | ||
1517 | inode->i_blocks = (inode->i_size + 511) >> 9; | ||
1518 | } | ||
1519 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; | ||
1520 | mark_inode_dirty(inode); | ||
1521 | invalidate_inode_pages(inode->i_mapping); | ||
1522 | |||
1523 | out_isem: | ||
1524 | return err; | ||
1525 | } /* jffs_file_write() */ | ||
1526 | |||
1527 | static int | ||
1528 | jffs_prepare_write(struct file *filp, struct page *page, | ||
1529 | unsigned from, unsigned to) | ||
1530 | { | ||
1531 | /* FIXME: we should detect some error conditions here */ | ||
1532 | |||
1533 | /* Bugger that. We should make sure the page is uptodate */ | ||
1534 | if (!PageUptodate(page) && (from || to < PAGE_CACHE_SIZE)) | ||
1535 | return jffs_do_readpage_nolock(filp, page); | ||
1536 | |||
1537 | return 0; | ||
1538 | } /* jffs_prepare_write() */ | ||
1539 | |||
1540 | static int | ||
1541 | jffs_commit_write(struct file *filp, struct page *page, | ||
1542 | unsigned from, unsigned to) | ||
1543 | { | ||
1544 | void *addr = page_address(page) + from; | ||
1545 | /* XXX: PAGE_CACHE_SHIFT or PAGE_SHIFT */ | ||
1546 | loff_t pos = page_offset(page) + from; | ||
1547 | |||
1548 | return jffs_file_write(filp, addr, to-from, &pos); | ||
1549 | } /* jffs_commit_write() */ | ||
1550 | |||
1551 | /* This is our ioctl() routine. */ | ||
1552 | static int | ||
1553 | jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
1554 | unsigned long arg) | ||
1555 | { | ||
1556 | struct jffs_control *c; | ||
1557 | int ret = 0; | ||
1558 | |||
1559 | D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n", | ||
1560 | cmd, arg)); | ||
1561 | |||
1562 | if (!(c = (struct jffs_control *)inode->i_sb->s_fs_info)) { | ||
1563 | printk(KERN_ERR "JFFS: Bad inode in ioctl() call. " | ||
1564 | "(cmd = 0x%08x)\n", cmd); | ||
1565 | return -EIO; | ||
1566 | } | ||
1567 | D3(printk (KERN_NOTICE "ioctl(): down biglock\n")); | ||
1568 | mutex_lock(&c->fmc->biglock); | ||
1569 | |||
1570 | switch (cmd) { | ||
1571 | case JFFS_PRINT_HASH: | ||
1572 | jffs_print_hash_table(c); | ||
1573 | break; | ||
1574 | case JFFS_PRINT_TREE: | ||
1575 | jffs_print_tree(c->root, 0); | ||
1576 | break; | ||
1577 | case JFFS_GET_STATUS: | ||
1578 | { | ||
1579 | struct jffs_flash_status fst; | ||
1580 | struct jffs_fmcontrol *fmc = c->fmc; | ||
1581 | printk("Flash status -- "); | ||
1582 | if (!access_ok(VERIFY_WRITE, | ||
1583 | (struct jffs_flash_status __user *)arg, | ||
1584 | sizeof(struct jffs_flash_status))) { | ||
1585 | D(printk("jffs_ioctl(): Bad arg in " | ||
1586 | "JFFS_GET_STATUS ioctl!\n")); | ||
1587 | ret = -EFAULT; | ||
1588 | break; | ||
1589 | } | ||
1590 | fst.size = fmc->flash_size; | ||
1591 | fst.used = fmc->used_size; | ||
1592 | fst.dirty = fmc->dirty_size; | ||
1593 | fst.begin = fmc->head->offset; | ||
1594 | fst.end = fmc->tail->offset + fmc->tail->size; | ||
1595 | printk("size: %d, used: %d, dirty: %d, " | ||
1596 | "begin: %d, end: %d\n", | ||
1597 | fst.size, fst.used, fst.dirty, | ||
1598 | fst.begin, fst.end); | ||
1599 | if (copy_to_user((struct jffs_flash_status __user *)arg, | ||
1600 | &fst, | ||
1601 | sizeof(struct jffs_flash_status))) { | ||
1602 | ret = -EFAULT; | ||
1603 | } | ||
1604 | } | ||
1605 | break; | ||
1606 | default: | ||
1607 | ret = -ENOTTY; | ||
1608 | } | ||
1609 | D3(printk (KERN_NOTICE "ioctl(): up biglock\n")); | ||
1610 | mutex_unlock(&c->fmc->biglock); | ||
1611 | return ret; | ||
1612 | } /* jffs_ioctl() */ | ||
1613 | |||
1614 | |||
1615 | static const struct address_space_operations jffs_address_operations = { | ||
1616 | .readpage = jffs_readpage, | ||
1617 | .prepare_write = jffs_prepare_write, | ||
1618 | .commit_write = jffs_commit_write, | ||
1619 | }; | ||
1620 | |||
1621 | static int jffs_fsync(struct file *f, struct dentry *d, int datasync) | ||
1622 | { | ||
1623 | /* We currently have O_SYNC operations at all times. | ||
1624 | Do nothing. | ||
1625 | */ | ||
1626 | return 0; | ||
1627 | } | ||
1628 | |||
1629 | |||
1630 | static const struct file_operations jffs_file_operations = | ||
1631 | { | ||
1632 | .open = generic_file_open, | ||
1633 | .llseek = generic_file_llseek, | ||
1634 | .read = do_sync_read, | ||
1635 | .aio_read = generic_file_aio_read, | ||
1636 | .write = do_sync_write, | ||
1637 | .aio_write = generic_file_aio_write, | ||
1638 | .ioctl = jffs_ioctl, | ||
1639 | .mmap = generic_file_readonly_mmap, | ||
1640 | .fsync = jffs_fsync, | ||
1641 | .sendfile = generic_file_sendfile, | ||
1642 | }; | ||
1643 | |||
1644 | |||
1645 | static struct inode_operations jffs_file_inode_operations = | ||
1646 | { | ||
1647 | .lookup = jffs_lookup, /* lookup */ | ||
1648 | .setattr = jffs_setattr, | ||
1649 | }; | ||
1650 | |||
1651 | |||
1652 | static const struct file_operations jffs_dir_operations = | ||
1653 | { | ||
1654 | .readdir = jffs_readdir, | ||
1655 | }; | ||
1656 | |||
1657 | |||
1658 | static struct inode_operations jffs_dir_inode_operations = | ||
1659 | { | ||
1660 | .create = jffs_create, | ||
1661 | .lookup = jffs_lookup, | ||
1662 | .unlink = jffs_unlink, | ||
1663 | .symlink = jffs_symlink, | ||
1664 | .mkdir = jffs_mkdir, | ||
1665 | .rmdir = jffs_rmdir, | ||
1666 | .mknod = jffs_mknod, | ||
1667 | .rename = jffs_rename, | ||
1668 | .setattr = jffs_setattr, | ||
1669 | }; | ||
1670 | |||
1671 | |||
1672 | /* Initialize an inode for the VFS. */ | ||
1673 | static void | ||
1674 | jffs_read_inode(struct inode *inode) | ||
1675 | { | ||
1676 | struct jffs_file *f; | ||
1677 | struct jffs_control *c; | ||
1678 | |||
1679 | D3(printk("jffs_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); | ||
1680 | |||
1681 | if (!inode->i_sb) { | ||
1682 | D(printk("jffs_read_inode(): !inode->i_sb ==> " | ||
1683 | "No super block!\n")); | ||
1684 | return; | ||
1685 | } | ||
1686 | c = (struct jffs_control *)inode->i_sb->s_fs_info; | ||
1687 | D3(printk (KERN_NOTICE "read_inode(): down biglock\n")); | ||
1688 | mutex_lock(&c->fmc->biglock); | ||
1689 | if (!(f = jffs_find_file(c, inode->i_ino))) { | ||
1690 | D(printk("jffs_read_inode(): No such inode (%lu).\n", | ||
1691 | inode->i_ino)); | ||
1692 | D3(printk (KERN_NOTICE "read_inode(): up biglock\n")); | ||
1693 | mutex_unlock(&c->fmc->biglock); | ||
1694 | return; | ||
1695 | } | ||
1696 | inode->i_private = f; | ||
1697 | inode->i_mode = f->mode; | ||
1698 | inode->i_nlink = f->nlink; | ||
1699 | inode->i_uid = f->uid; | ||
1700 | inode->i_gid = f->gid; | ||
1701 | inode->i_size = f->size; | ||
1702 | inode->i_atime.tv_sec = f->atime; | ||
1703 | inode->i_mtime.tv_sec = f->mtime; | ||
1704 | inode->i_ctime.tv_sec = f->ctime; | ||
1705 | inode->i_atime.tv_nsec = | ||
1706 | inode->i_mtime.tv_nsec = | ||
1707 | inode->i_ctime.tv_nsec = 0; | ||
1708 | |||
1709 | inode->i_blocks = (inode->i_size + 511) >> 9; | ||
1710 | if (S_ISREG(inode->i_mode)) { | ||
1711 | inode->i_op = &jffs_file_inode_operations; | ||
1712 | inode->i_fop = &jffs_file_operations; | ||
1713 | inode->i_mapping->a_ops = &jffs_address_operations; | ||
1714 | } | ||
1715 | else if (S_ISDIR(inode->i_mode)) { | ||
1716 | inode->i_op = &jffs_dir_inode_operations; | ||
1717 | inode->i_fop = &jffs_dir_operations; | ||
1718 | } | ||
1719 | else if (S_ISLNK(inode->i_mode)) { | ||
1720 | inode->i_op = &page_symlink_inode_operations; | ||
1721 | inode->i_mapping->a_ops = &jffs_address_operations; | ||
1722 | } | ||
1723 | else { | ||
1724 | /* If the node is a device of some sort, then the number of | ||
1725 | the device should be read from the flash memory and then | ||
1726 | added to the inode's i_rdev member. */ | ||
1727 | u16 val; | ||
1728 | jffs_read_data(f, (char *)&val, 0, 2); | ||
1729 | init_special_inode(inode, inode->i_mode, | ||
1730 | old_decode_dev(val)); | ||
1731 | } | ||
1732 | |||
1733 | D3(printk (KERN_NOTICE "read_inode(): up biglock\n")); | ||
1734 | mutex_unlock(&c->fmc->biglock); | ||
1735 | } | ||
1736 | |||
1737 | |||
1738 | static void | ||
1739 | jffs_delete_inode(struct inode *inode) | ||
1740 | { | ||
1741 | struct jffs_file *f; | ||
1742 | struct jffs_control *c; | ||
1743 | D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n", | ||
1744 | inode->i_ino)); | ||
1745 | |||
1746 | truncate_inode_pages(&inode->i_data, 0); | ||
1747 | lock_kernel(); | ||
1748 | inode->i_size = 0; | ||
1749 | inode->i_blocks = 0; | ||
1750 | inode->i_private = NULL; | ||
1751 | clear_inode(inode); | ||
1752 | if (inode->i_nlink == 0) { | ||
1753 | c = (struct jffs_control *) inode->i_sb->s_fs_info; | ||
1754 | f = (struct jffs_file *) jffs_find_file (c, inode->i_ino); | ||
1755 | jffs_possibly_delete_file(f); | ||
1756 | } | ||
1757 | |||
1758 | unlock_kernel(); | ||
1759 | } | ||
1760 | |||
1761 | |||
1762 | static void | ||
1763 | jffs_write_super(struct super_block *sb) | ||
1764 | { | ||
1765 | struct jffs_control *c = (struct jffs_control *)sb->s_fs_info; | ||
1766 | lock_kernel(); | ||
1767 | jffs_garbage_collect_trigger(c); | ||
1768 | unlock_kernel(); | ||
1769 | } | ||
1770 | |||
1771 | static int jffs_remount(struct super_block *sb, int *flags, char *data) | ||
1772 | { | ||
1773 | *flags |= MS_NODIRATIME; | ||
1774 | return 0; | ||
1775 | } | ||
1776 | |||
1777 | static struct super_operations jffs_ops = | ||
1778 | { | ||
1779 | .read_inode = jffs_read_inode, | ||
1780 | .delete_inode = jffs_delete_inode, | ||
1781 | .put_super = jffs_put_super, | ||
1782 | .write_super = jffs_write_super, | ||
1783 | .statfs = jffs_statfs, | ||
1784 | .remount_fs = jffs_remount, | ||
1785 | }; | ||
1786 | |||
1787 | static int jffs_get_sb(struct file_system_type *fs_type, | ||
1788 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | ||
1789 | { | ||
1790 | return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super, | ||
1791 | mnt); | ||
1792 | } | ||
1793 | |||
1794 | static struct file_system_type jffs_fs_type = { | ||
1795 | .owner = THIS_MODULE, | ||
1796 | .name = "jffs", | ||
1797 | .get_sb = jffs_get_sb, | ||
1798 | .kill_sb = kill_block_super, | ||
1799 | .fs_flags = FS_REQUIRES_DEV, | ||
1800 | }; | ||
1801 | |||
1802 | static int __init | ||
1803 | init_jffs_fs(void) | ||
1804 | { | ||
1805 | printk(KERN_INFO "JFFS version " JFFS_VERSION_STRING | ||
1806 | ", (C) 1999, 2000 Axis Communications AB\n"); | ||
1807 | |||
1808 | #ifdef CONFIG_JFFS_PROC_FS | ||
1809 | jffs_proc_root = proc_mkdir("jffs", proc_root_fs); | ||
1810 | if (!jffs_proc_root) { | ||
1811 | printk(KERN_WARNING "cannot create /proc/jffs entry\n"); | ||
1812 | } | ||
1813 | #endif | ||
1814 | fm_cache = kmem_cache_create("jffs_fm", sizeof(struct jffs_fm), | ||
1815 | 0, | ||
1816 | SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, | ||
1817 | NULL, NULL); | ||
1818 | if (!fm_cache) { | ||
1819 | return -ENOMEM; | ||
1820 | } | ||
1821 | |||
1822 | node_cache = kmem_cache_create("jffs_node",sizeof(struct jffs_node), | ||
1823 | 0, | ||
1824 | SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, | ||
1825 | NULL, NULL); | ||
1826 | if (!node_cache) { | ||
1827 | kmem_cache_destroy(fm_cache); | ||
1828 | return -ENOMEM; | ||
1829 | } | ||
1830 | |||
1831 | return register_filesystem(&jffs_fs_type); | ||
1832 | } | ||
1833 | |||
1834 | static void __exit | ||
1835 | exit_jffs_fs(void) | ||
1836 | { | ||
1837 | unregister_filesystem(&jffs_fs_type); | ||
1838 | kmem_cache_destroy(fm_cache); | ||
1839 | kmem_cache_destroy(node_cache); | ||
1840 | } | ||
1841 | |||
1842 | module_init(init_jffs_fs) | ||
1843 | module_exit(exit_jffs_fs) | ||
1844 | |||
1845 | MODULE_DESCRIPTION("The Journalling Flash File System"); | ||
1846 | MODULE_AUTHOR("Axis Communications AB."); | ||
1847 | MODULE_LICENSE("GPL"); | ||
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c deleted file mode 100644 index 6dd18911b44c..000000000000 --- a/fs/jffs/intrep.c +++ /dev/null | |||
@@ -1,3449 +0,0 @@ | |||
1 | /* | ||
2 | * JFFS -- Journaling Flash File System, Linux implementation. | ||
3 | * | ||
4 | * Copyright (C) 1999, 2000 Axis Communications, Inc. | ||
5 | * | ||
6 | * Created by Finn Hakansson <finn@axis.com>. | ||
7 | * | ||
8 | * This is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * $Id: intrep.c,v 1.102 2001/09/23 23:28:36 dwmw2 Exp $ | ||
14 | * | ||
15 | * Ported to Linux 2.3.x and MTD: | ||
16 | * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | /* This file contains the code for the internal structure of the | ||
21 | Journaling Flash File System, JFFS. */ | ||
22 | |||
23 | /* | ||
24 | * Todo list: | ||
25 | * | ||
26 | * memcpy_to_flash() and memcpy_from_flash() functions. | ||
27 | * | ||
28 | * Implementation of hard links. | ||
29 | * | ||
30 | * Organize the source code in a better way. Against the VFS we could | ||
31 | * have jffs_ext.c, and against the block device jffs_int.c. | ||
32 | * A better file-internal organization too. | ||
33 | * | ||
34 | * A better checksum algorithm. | ||
35 | * | ||
36 | * Consider endianness stuff. ntohl() etc. | ||
37 | * | ||
38 | * Are we handling the atime, mtime, ctime members of the inode right? | ||
39 | * | ||
40 | * Remove some duplicated code. Take a look at jffs_write_node() and | ||
41 | * jffs_rewrite_data() for instance. | ||
42 | * | ||
43 | * Implement more meaning of the nlink member in various data structures. | ||
44 | * nlink could be used in conjunction with hard links for instance. | ||
45 | * | ||
46 | * Better memory management. Allocate data structures in larger chunks | ||
47 | * if possible. | ||
48 | * | ||
49 | * If too much meta data is stored, a garbage collect should be issued. | ||
50 | * We have experienced problems with too much meta data with for instance | ||
51 | * log files. | ||
52 | * | ||
53 | * Improve the calls to jffs_ioctl(). We would like to retrieve more | ||
54 | * information to be able to debug (or to supervise) JFFS during run-time. | ||
55 | * | ||
56 | */ | ||
57 | |||
58 | #include <linux/types.h> | ||
59 | #include <linux/slab.h> | ||
60 | #include <linux/jffs.h> | ||
61 | #include <linux/fs.h> | ||
62 | #include <linux/stat.h> | ||
63 | #include <linux/pagemap.h> | ||
64 | #include <linux/mutex.h> | ||
65 | #include <asm/byteorder.h> | ||
66 | #include <linux/smp_lock.h> | ||
67 | #include <linux/time.h> | ||
68 | #include <linux/ctype.h> | ||
69 | #include <linux/freezer.h> | ||
70 | |||
71 | #include "intrep.h" | ||
72 | #include "jffs_fm.h" | ||
73 | |||
74 | long no_jffs_node = 0; | ||
75 | static long no_jffs_file = 0; | ||
76 | #if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG | ||
77 | long no_jffs_control = 0; | ||
78 | long no_jffs_raw_inode = 0; | ||
79 | long no_jffs_node_ref = 0; | ||
80 | long no_jffs_fm = 0; | ||
81 | long no_jffs_fmcontrol = 0; | ||
82 | long no_hash = 0; | ||
83 | long no_name = 0; | ||
84 | #endif | ||
85 | |||
86 | static int jffs_scan_flash(struct jffs_control *c); | ||
87 | static int jffs_update_file(struct jffs_file *f, struct jffs_node *node); | ||
88 | static int jffs_build_file(struct jffs_file *f); | ||
89 | static int jffs_free_file(struct jffs_file *f); | ||
90 | static int jffs_free_node_list(struct jffs_file *f); | ||
91 | static int jffs_garbage_collect_now(struct jffs_control *c); | ||
92 | static int jffs_insert_file_into_hash(struct jffs_file *f); | ||
93 | static int jffs_remove_redundant_nodes(struct jffs_file *f); | ||
94 | |||
95 | /* Is there enough space on the flash? */ | ||
96 | static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c, __u32 space) | ||
97 | { | ||
98 | struct jffs_fmcontrol *fmc = c->fmc; | ||
99 | |||
100 | while (1) { | ||
101 | if ((fmc->flash_size - (fmc->used_size + fmc->dirty_size)) | ||
102 | >= fmc->min_free_size + space) { | ||
103 | return 1; | ||
104 | } | ||
105 | if (fmc->dirty_size < fmc->sector_size) | ||
106 | return 0; | ||
107 | |||
108 | if (jffs_garbage_collect_now(c)) { | ||
109 | D1(printk("JFFS_ENOUGH_SPACE: jffs_garbage_collect_now() failed.\n")); | ||
110 | return 0; | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | |||
115 | #if CONFIG_JFFS_FS_VERBOSE > 0 | ||
116 | static __u8 | ||
117 | flash_read_u8(struct mtd_info *mtd, loff_t from) | ||
118 | { | ||
119 | size_t retlen; | ||
120 | __u8 ret; | ||
121 | int res; | ||
122 | |||
123 | res = MTD_READ(mtd, from, 1, &retlen, &ret); | ||
124 | if (retlen != 1) { | ||
125 | printk("Didn't read a byte in flash_read_u8(). Returned %d\n", res); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | static void | ||
133 | jffs_hexdump(struct mtd_info *mtd, loff_t pos, int size) | ||
134 | { | ||
135 | char line[16]; | ||
136 | int j = 0; | ||
137 | |||
138 | while (size > 0) { | ||
139 | int i; | ||
140 | |||
141 | printk("%ld:", (long) pos); | ||
142 | for (j = 0; j < 16; j++) { | ||
143 | line[j] = flash_read_u8(mtd, pos++); | ||
144 | } | ||
145 | for (i = 0; i < j; i++) { | ||
146 | if (!(i & 1)) { | ||
147 | printk(" %.2x", line[i] & 0xff); | ||
148 | } | ||
149 | else { | ||
150 | printk("%.2x", line[i] & 0xff); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | /* Print empty space */ | ||
155 | for (; i < 16; i++) { | ||
156 | if (!(i & 1)) { | ||
157 | printk(" "); | ||
158 | } | ||
159 | else { | ||
160 | printk(" "); | ||
161 | } | ||
162 | } | ||
163 | printk(" "); | ||
164 | |||
165 | for (i = 0; i < j; i++) { | ||
166 | if (isgraph(line[i])) { | ||
167 | printk("%c", line[i]); | ||
168 | } | ||
169 | else { | ||
170 | printk("."); | ||
171 | } | ||
172 | } | ||
173 | printk("\n"); | ||
174 | size -= 16; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* Print the contents of a node. */ | ||
179 | static void | ||
180 | jffs_print_node(struct jffs_node *n) | ||
181 | { | ||
182 | D(printk("jffs_node: 0x%p\n", n)); | ||
183 | D(printk("{\n")); | ||
184 | D(printk(" 0x%08x, /* version */\n", n->version)); | ||
185 | D(printk(" 0x%08x, /* data_offset */\n", n->data_offset)); | ||
186 | D(printk(" 0x%08x, /* data_size */\n", n->data_size)); | ||
187 | D(printk(" 0x%08x, /* removed_size */\n", n->removed_size)); | ||
188 | D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset)); | ||
189 | D(printk(" 0x%02x, /* name_size */\n", n->name_size)); | ||
190 | D(printk(" 0x%p, /* fm, fm->offset: %u */\n", | ||
191 | n->fm, (n->fm ? n->fm->offset : 0))); | ||
192 | D(printk(" 0x%p, /* version_prev */\n", n->version_prev)); | ||
193 | D(printk(" 0x%p, /* version_next */\n", n->version_next)); | ||
194 | D(printk(" 0x%p, /* range_prev */\n", n->range_prev)); | ||
195 | D(printk(" 0x%p, /* range_next */\n", n->range_next)); | ||
196 | D(printk("}\n")); | ||
197 | } | ||
198 | |||
199 | #endif | ||
200 | |||
201 | /* Print the contents of a raw inode. */ | ||
202 | static void | ||
203 | jffs_print_raw_inode(struct jffs_raw_inode *raw_inode) | ||
204 | { | ||
205 | D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino)); | ||
206 | D(printk("{\n")); | ||
207 | D(printk(" 0x%08x, /* magic */\n", raw_inode->magic)); | ||
208 | D(printk(" 0x%08x, /* ino */\n", raw_inode->ino)); | ||
209 | D(printk(" 0x%08x, /* pino */\n", raw_inode->pino)); | ||
210 | D(printk(" 0x%08x, /* version */\n", raw_inode->version)); | ||
211 | D(printk(" 0x%08x, /* mode */\n", raw_inode->mode)); | ||
212 | D(printk(" 0x%04x, /* uid */\n", raw_inode->uid)); | ||
213 | D(printk(" 0x%04x, /* gid */\n", raw_inode->gid)); | ||
214 | D(printk(" 0x%08x, /* atime */\n", raw_inode->atime)); | ||
215 | D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime)); | ||
216 | D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime)); | ||
217 | D(printk(" 0x%08x, /* offset */\n", raw_inode->offset)); | ||
218 | D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize)); | ||
219 | D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize)); | ||
220 | D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize)); | ||
221 | D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink)); | ||
222 | D(printk(" 0x%02x, /* spare */\n", | ||
223 | raw_inode->spare)); | ||
224 | D(printk(" %u, /* rename */\n", | ||
225 | raw_inode->rename)); | ||
226 | D(printk(" %u, /* deleted */\n", | ||
227 | raw_inode->deleted)); | ||
228 | D(printk(" 0x%02x, /* accurate */\n", | ||
229 | raw_inode->accurate)); | ||
230 | D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum)); | ||
231 | D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum)); | ||
232 | D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum)); | ||
233 | D(printk("}\n")); | ||
234 | } | ||
235 | |||
236 | #define flash_safe_acquire(arg) | ||
237 | #define flash_safe_release(arg) | ||
238 | |||
239 | |||
240 | static int | ||
241 | flash_safe_read(struct mtd_info *mtd, loff_t from, | ||
242 | u_char *buf, size_t count) | ||
243 | { | ||
244 | size_t retlen; | ||
245 | int res; | ||
246 | |||
247 | D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n", | ||
248 | mtd, (unsigned int) from, buf, count)); | ||
249 | |||
250 | res = mtd->read(mtd, from, count, &retlen, buf); | ||
251 | if (retlen != count) { | ||
252 | panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res); | ||
253 | } | ||
254 | return res?res:retlen; | ||
255 | } | ||
256 | |||
257 | |||
258 | static __u32 | ||
259 | flash_read_u32(struct mtd_info *mtd, loff_t from) | ||
260 | { | ||
261 | size_t retlen; | ||
262 | __u32 ret; | ||
263 | int res; | ||
264 | |||
265 | res = mtd->read(mtd, from, 4, &retlen, (unsigned char *)&ret); | ||
266 | if (retlen != 4) { | ||
267 | printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res); | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | |||
275 | static int | ||
276 | flash_safe_write(struct mtd_info *mtd, loff_t to, | ||
277 | const u_char *buf, size_t count) | ||
278 | { | ||
279 | size_t retlen; | ||
280 | int res; | ||
281 | |||
282 | D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n", | ||
283 | mtd, (unsigned int) to, buf, count)); | ||
284 | |||
285 | res = mtd->write(mtd, to, count, &retlen, buf); | ||
286 | if (retlen != count) { | ||
287 | printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res); | ||
288 | } | ||
289 | return res?res:retlen; | ||
290 | } | ||
291 | |||
292 | |||
293 | static int | ||
294 | flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs, | ||
295 | unsigned long iovec_cnt, loff_t to) | ||
296 | { | ||
297 | size_t retlen, retlen_a; | ||
298 | int i; | ||
299 | int res; | ||
300 | |||
301 | D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n", | ||
302 | mtd, (unsigned int) to, vecs)); | ||
303 | |||
304 | if (mtd->writev) { | ||
305 | res = mtd->writev(mtd, vecs, iovec_cnt, to, &retlen); | ||
306 | return res ? res : retlen; | ||
307 | } | ||
308 | /* Not implemented writev. Repeatedly use write - on the not so | ||
309 | unreasonable assumption that the mtd driver doesn't care how | ||
310 | many write cycles we use. */ | ||
311 | res=0; | ||
312 | retlen=0; | ||
313 | |||
314 | for (i=0; !res && i<iovec_cnt; i++) { | ||
315 | res = mtd->write(mtd, to, vecs[i].iov_len, &retlen_a, | ||
316 | vecs[i].iov_base); | ||
317 | if (retlen_a != vecs[i].iov_len) { | ||
318 | printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res); | ||
319 | if (i != iovec_cnt-1) | ||
320 | return -EIO; | ||
321 | } | ||
322 | /* If res is non-zero, retlen_a is undefined, but we don't | ||
323 | care because in that case it's not going to be | ||
324 | returned anyway. | ||
325 | */ | ||
326 | to += retlen_a; | ||
327 | retlen += retlen_a; | ||
328 | } | ||
329 | return res?res:retlen; | ||
330 | } | ||
331 | |||
332 | |||
333 | static int | ||
334 | flash_memset(struct mtd_info *mtd, loff_t to, | ||
335 | const u_char c, size_t size) | ||
336 | { | ||
337 | static unsigned char pattern[64]; | ||
338 | int i; | ||
339 | |||
340 | /* fill up pattern */ | ||
341 | |||
342 | for(i = 0; i < 64; i++) | ||
343 | pattern[i] = c; | ||
344 | |||
345 | /* write as many 64-byte chunks as we can */ | ||
346 | |||
347 | while (size >= 64) { | ||
348 | flash_safe_write(mtd, to, pattern, 64); | ||
349 | size -= 64; | ||
350 | to += 64; | ||
351 | } | ||
352 | |||
353 | /* and the rest */ | ||
354 | |||
355 | if(size) | ||
356 | flash_safe_write(mtd, to, pattern, size); | ||
357 | |||
358 | return size; | ||
359 | } | ||
360 | |||
361 | |||
362 | static void | ||
363 | intrep_erase_callback(struct erase_info *done) | ||
364 | { | ||
365 | wait_queue_head_t *wait_q; | ||
366 | |||
367 | wait_q = (wait_queue_head_t *)done->priv; | ||
368 | |||
369 | wake_up(wait_q); | ||
370 | } | ||
371 | |||
372 | |||
373 | static int | ||
374 | flash_erase_region(struct mtd_info *mtd, loff_t start, | ||
375 | size_t size) | ||
376 | { | ||
377 | struct erase_info *erase; | ||
378 | DECLARE_WAITQUEUE(wait, current); | ||
379 | wait_queue_head_t wait_q; | ||
380 | |||
381 | erase = kmalloc(sizeof(struct erase_info), GFP_KERNEL); | ||
382 | if (!erase) | ||
383 | return -ENOMEM; | ||
384 | |||
385 | init_waitqueue_head(&wait_q); | ||
386 | |||
387 | erase->mtd = mtd; | ||
388 | erase->callback = intrep_erase_callback; | ||
389 | erase->addr = start; | ||
390 | erase->len = size; | ||
391 | erase->priv = (u_long)&wait_q; | ||
392 | |||
393 | /* FIXME: Use TASK_INTERRUPTIBLE and deal with being interrupted */ | ||
394 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
395 | add_wait_queue(&wait_q, &wait); | ||
396 | |||
397 | if (mtd->erase(mtd, erase) < 0) { | ||
398 | set_current_state(TASK_RUNNING); | ||
399 | remove_wait_queue(&wait_q, &wait); | ||
400 | kfree(erase); | ||
401 | |||
402 | printk(KERN_WARNING "flash: erase of region [0x%lx, 0x%lx] " | ||
403 | "totally failed\n", (long)start, (long)start + size); | ||
404 | |||
405 | return -1; | ||
406 | } | ||
407 | |||
408 | schedule(); /* Wait for flash to finish. */ | ||
409 | remove_wait_queue(&wait_q, &wait); | ||
410 | |||
411 | kfree(erase); | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | /* This routine calculates checksums in JFFS. */ | ||
417 | static __u32 | ||
418 | jffs_checksum(const void *data, int size) | ||
419 | { | ||
420 | __u32 sum = 0; | ||
421 | __u8 *ptr = (__u8 *)data; | ||
422 | while (size-- > 0) { | ||
423 | sum += *ptr++; | ||
424 | } | ||
425 | D3(printk(", result: 0x%08x\n", sum)); | ||
426 | return sum; | ||
427 | } | ||
428 | |||
429 | |||
430 | static int | ||
431 | jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result) | ||
432 | { | ||
433 | __u32 sum = 0; | ||
434 | loff_t ptr = start; | ||
435 | __u8 *read_buf; | ||
436 | int i, length; | ||
437 | |||
438 | /* Allocate read buffer */ | ||
439 | read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL); | ||
440 | if (!read_buf) { | ||
441 | printk(KERN_NOTICE "kmalloc failed in jffs_checksum_flash()\n"); | ||
442 | return -ENOMEM; | ||
443 | } | ||
444 | /* Loop until checksum done */ | ||
445 | while (size) { | ||
446 | /* Get amount of data to read */ | ||
447 | if (size < 4096) | ||
448 | length = size; | ||
449 | else | ||
450 | length = 4096; | ||
451 | |||
452 | /* Perform flash read */ | ||
453 | D3(printk(KERN_NOTICE "jffs_checksum_flash\n")); | ||
454 | flash_safe_read(mtd, ptr, &read_buf[0], length); | ||
455 | |||
456 | /* Compute checksum */ | ||
457 | for (i=0; i < length ; i++) | ||
458 | sum += read_buf[i]; | ||
459 | |||
460 | /* Update pointer and size */ | ||
461 | size -= length; | ||
462 | ptr += length; | ||
463 | } | ||
464 | |||
465 | /* Free read buffer */ | ||
466 | kfree(read_buf); | ||
467 | |||
468 | /* Return result */ | ||
469 | D3(printk("checksum result: 0x%08x\n", sum)); | ||
470 | *result = sum; | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static __inline__ void jffs_fm_write_lock(struct jffs_fmcontrol *fmc) | ||
475 | { | ||
476 | // down(&fmc->wlock); | ||
477 | } | ||
478 | |||
479 | static __inline__ void jffs_fm_write_unlock(struct jffs_fmcontrol *fmc) | ||
480 | { | ||
481 | // up(&fmc->wlock); | ||
482 | } | ||
483 | |||
484 | |||
485 | /* Create and initialize a new struct jffs_file. */ | ||
486 | static struct jffs_file * | ||
487 | jffs_create_file(struct jffs_control *c, | ||
488 | const struct jffs_raw_inode *raw_inode) | ||
489 | { | ||
490 | struct jffs_file *f; | ||
491 | |||
492 | if (!(f = kzalloc(sizeof(*f), GFP_KERNEL))) { | ||
493 | D(printk("jffs_create_file(): Failed!\n")); | ||
494 | return NULL; | ||
495 | } | ||
496 | no_jffs_file++; | ||
497 | f->ino = raw_inode->ino; | ||
498 | f->pino = raw_inode->pino; | ||
499 | f->nlink = raw_inode->nlink; | ||
500 | f->deleted = raw_inode->deleted; | ||
501 | f->c = c; | ||
502 | |||
503 | return f; | ||
504 | } | ||
505 | |||
506 | |||
507 | /* Build a control block for the file system. */ | ||
508 | static struct jffs_control * | ||
509 | jffs_create_control(struct super_block *sb) | ||
510 | { | ||
511 | struct jffs_control *c; | ||
512 | register int s = sizeof(struct jffs_control); | ||
513 | int i; | ||
514 | D(char *t = 0); | ||
515 | |||
516 | D2(printk("jffs_create_control()\n")); | ||
517 | |||
518 | if (!(c = kmalloc(s, GFP_KERNEL))) { | ||
519 | goto fail_control; | ||
520 | } | ||
521 | DJM(no_jffs_control++); | ||
522 | c->root = NULL; | ||
523 | c->gc_task = NULL; | ||
524 | c->hash_len = JFFS_HASH_SIZE; | ||
525 | s = sizeof(struct list_head) * c->hash_len; | ||
526 | if (!(c->hash = kmalloc(s, GFP_KERNEL))) { | ||
527 | goto fail_hash; | ||
528 | } | ||
529 | DJM(no_hash++); | ||
530 | for (i = 0; i < c->hash_len; i++) | ||
531 | INIT_LIST_HEAD(&c->hash[i]); | ||
532 | if (!(c->fmc = jffs_build_begin(c, MINOR(sb->s_dev)))) { | ||
533 | goto fail_fminit; | ||
534 | } | ||
535 | c->next_ino = JFFS_MIN_INO + 1; | ||
536 | c->delete_list = (struct jffs_delete_list *) 0; | ||
537 | return c; | ||
538 | |||
539 | fail_fminit: | ||
540 | D(t = "c->fmc"); | ||
541 | fail_hash: | ||
542 | kfree(c); | ||
543 | DJM(no_jffs_control--); | ||
544 | D(t = t ? t : "c->hash"); | ||
545 | fail_control: | ||
546 | D(t = t ? t : "control"); | ||
547 | D(printk("jffs_create_control(): Allocation failed: (%s)\n", t)); | ||
548 | return (struct jffs_control *)0; | ||
549 | } | ||
550 | |||
551 | |||
552 | /* Clean up all data structures associated with the file system. */ | ||
553 | void | ||
554 | jffs_cleanup_control(struct jffs_control *c) | ||
555 | { | ||
556 | D2(printk("jffs_cleanup_control()\n")); | ||
557 | |||
558 | if (!c) { | ||
559 | D(printk("jffs_cleanup_control(): c == NULL !!!\n")); | ||
560 | return; | ||
561 | } | ||
562 | |||
563 | while (c->delete_list) { | ||
564 | struct jffs_delete_list *delete_list_element; | ||
565 | delete_list_element = c->delete_list; | ||
566 | c->delete_list = c->delete_list->next; | ||
567 | kfree(delete_list_element); | ||
568 | } | ||
569 | |||
570 | /* Free all files and nodes. */ | ||
571 | if (c->hash) { | ||
572 | jffs_foreach_file(c, jffs_free_node_list); | ||
573 | jffs_foreach_file(c, jffs_free_file); | ||
574 | kfree(c->hash); | ||
575 | DJM(no_hash--); | ||
576 | } | ||
577 | jffs_cleanup_fmcontrol(c->fmc); | ||
578 | kfree(c); | ||
579 | DJM(no_jffs_control--); | ||
580 | D3(printk("jffs_cleanup_control(): Leaving...\n")); | ||
581 | } | ||
582 | |||
583 | |||
584 | /* This function adds a virtual root node to the in-RAM representation. | ||
585 | Called by jffs_build_fs(). */ | ||
586 | static int | ||
587 | jffs_add_virtual_root(struct jffs_control *c) | ||
588 | { | ||
589 | struct jffs_file *root; | ||
590 | struct jffs_node *node; | ||
591 | |||
592 | D2(printk("jffs_add_virtual_root(): " | ||
593 | "Creating a virtual root directory.\n")); | ||
594 | |||
595 | if (!(root = kzalloc(sizeof(struct jffs_file), GFP_KERNEL))) { | ||
596 | return -ENOMEM; | ||
597 | } | ||
598 | no_jffs_file++; | ||
599 | if (!(node = jffs_alloc_node())) { | ||
600 | kfree(root); | ||
601 | no_jffs_file--; | ||
602 | return -ENOMEM; | ||
603 | } | ||
604 | DJM(no_jffs_node++); | ||
605 | memset(node, 0, sizeof(struct jffs_node)); | ||
606 | node->ino = JFFS_MIN_INO; | ||
607 | root->ino = JFFS_MIN_INO; | ||
608 | root->mode = S_IFDIR | S_IRWXU | S_IRGRP | ||
609 | | S_IXGRP | S_IROTH | S_IXOTH; | ||
610 | root->atime = root->mtime = root->ctime = get_seconds(); | ||
611 | root->nlink = 1; | ||
612 | root->c = c; | ||
613 | root->version_head = root->version_tail = node; | ||
614 | jffs_insert_file_into_hash(root); | ||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | |||
619 | /* This is where the file system is built and initialized. */ | ||
620 | int | ||
621 | jffs_build_fs(struct super_block *sb) | ||
622 | { | ||
623 | struct jffs_control *c; | ||
624 | int err = 0; | ||
625 | |||
626 | D2(printk("jffs_build_fs()\n")); | ||
627 | |||
628 | if (!(c = jffs_create_control(sb))) { | ||
629 | return -ENOMEM; | ||
630 | } | ||
631 | c->building_fs = 1; | ||
632 | c->sb = sb; | ||
633 | if ((err = jffs_scan_flash(c)) < 0) { | ||
634 | if(err == -EAGAIN){ | ||
635 | /* scan_flash() wants us to try once more. A flipping | ||
636 | bits sector was detect in the middle of the scan flash. | ||
637 | Clean up old allocated memory before going in. | ||
638 | */ | ||
639 | D1(printk("jffs_build_fs: Cleaning up all control structures," | ||
640 | " reallocating them and trying mount again.\n")); | ||
641 | jffs_cleanup_control(c); | ||
642 | if (!(c = jffs_create_control(sb))) { | ||
643 | return -ENOMEM; | ||
644 | } | ||
645 | c->building_fs = 1; | ||
646 | c->sb = sb; | ||
647 | |||
648 | if ((err = jffs_scan_flash(c)) < 0) { | ||
649 | goto jffs_build_fs_fail; | ||
650 | } | ||
651 | }else{ | ||
652 | goto jffs_build_fs_fail; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | /* Add a virtual root node if no one exists. */ | ||
657 | if (!jffs_find_file(c, JFFS_MIN_INO)) { | ||
658 | if ((err = jffs_add_virtual_root(c)) < 0) { | ||
659 | goto jffs_build_fs_fail; | ||
660 | } | ||
661 | } | ||
662 | |||
663 | while (c->delete_list) { | ||
664 | struct jffs_file *f; | ||
665 | struct jffs_delete_list *delete_list_element; | ||
666 | |||
667 | if ((f = jffs_find_file(c, c->delete_list->ino))) { | ||
668 | f->deleted = 1; | ||
669 | } | ||
670 | delete_list_element = c->delete_list; | ||
671 | c->delete_list = c->delete_list->next; | ||
672 | kfree(delete_list_element); | ||
673 | } | ||
674 | |||
675 | /* Remove deleted nodes. */ | ||
676 | if ((err = jffs_foreach_file(c, jffs_possibly_delete_file)) < 0) { | ||
677 | printk(KERN_ERR "JFFS: Failed to remove deleted nodes.\n"); | ||
678 | goto jffs_build_fs_fail; | ||
679 | } | ||
680 | /* Remove redundant nodes. (We are not interested in the | ||
681 | return value in this case.) */ | ||
682 | jffs_foreach_file(c, jffs_remove_redundant_nodes); | ||
683 | /* Try to build a tree from all the nodes. */ | ||
684 | if ((err = jffs_foreach_file(c, jffs_insert_file_into_tree)) < 0) { | ||
685 | printk("JFFS: Failed to build tree.\n"); | ||
686 | goto jffs_build_fs_fail; | ||
687 | } | ||
688 | /* Compute the sizes of all files in the filesystem. Adjust if | ||
689 | necessary. */ | ||
690 | if ((err = jffs_foreach_file(c, jffs_build_file)) < 0) { | ||
691 | printk("JFFS: Failed to build file system.\n"); | ||
692 | goto jffs_build_fs_fail; | ||
693 | } | ||
694 | sb->s_fs_info = (void *)c; | ||
695 | c->building_fs = 0; | ||
696 | |||
697 | D1(jffs_print_hash_table(c)); | ||
698 | D1(jffs_print_tree(c->root, 0)); | ||
699 | |||
700 | return 0; | ||
701 | |||
702 | jffs_build_fs_fail: | ||
703 | jffs_cleanup_control(c); | ||
704 | return err; | ||
705 | } /* jffs_build_fs() */ | ||
706 | |||
707 | |||
708 | /* | ||
709 | This checks for sectors that were being erased in their previous | ||
710 | lifetimes and for some reason or the other (power fail etc.), | ||
711 | the erase cycles never completed. | ||
712 | As the flash array would have reverted back to read status, | ||
713 | these sectors are detected by the symptom of the "flipping bits", | ||
714 | i.e. bits being read back differently from the same location in | ||
715 | flash if read multiple times. | ||
716 | The only solution to this is to re-erase the entire | ||
717 | sector. | ||
718 | Unfortunately detecting "flipping bits" is not a simple exercise | ||
719 | as a bit may be read back at 1 or 0 depending on the alignment | ||
720 | of the stars in the universe. | ||
721 | The level of confidence is in direct proportion to the number of | ||
722 | scans done. By power fail testing I (Vipin) have been able to | ||
723 | proove that reading twice is not enough. | ||
724 | Maybe 4 times? Change NUM_REREADS to a higher number if you want | ||
725 | a (even) higher degree of confidence in your mount process. | ||
726 | A higher number would of course slow down your mount. | ||
727 | */ | ||
728 | static int check_partly_erased_sectors(struct jffs_fmcontrol *fmc){ | ||
729 | |||
730 | #define NUM_REREADS 4 /* see note above */ | ||
731 | #define READ_AHEAD_BYTES 4096 /* must be a multiple of 4, | ||
732 | usually set to kernel page size */ | ||
733 | |||
734 | __u8 *read_buf1; | ||
735 | __u8 *read_buf2; | ||
736 | |||
737 | int err = 0; | ||
738 | int retlen; | ||
739 | int i; | ||
740 | int cnt; | ||
741 | __u32 offset; | ||
742 | loff_t pos = 0; | ||
743 | loff_t end = fmc->flash_size; | ||
744 | |||
745 | |||
746 | /* Allocate read buffers */ | ||
747 | read_buf1 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL); | ||
748 | if (!read_buf1) | ||
749 | return -ENOMEM; | ||
750 | |||
751 | read_buf2 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL); | ||
752 | if (!read_buf2) { | ||
753 | kfree(read_buf1); | ||
754 | return -ENOMEM; | ||
755 | } | ||
756 | |||
757 | CHECK_NEXT: | ||
758 | while(pos < end){ | ||
759 | |||
760 | D1(printk("check_partly_erased_sector():checking sector which contains" | ||
761 | " offset 0x%x for flipping bits..\n", (__u32)pos)); | ||
762 | |||
763 | retlen = flash_safe_read(fmc->mtd, pos, | ||
764 | &read_buf1[0], READ_AHEAD_BYTES); | ||
765 | retlen &= ~3; | ||
766 | |||
767 | for(cnt = 0; cnt < NUM_REREADS; cnt++){ | ||
768 | (void)flash_safe_read(fmc->mtd, pos, | ||
769 | &read_buf2[0], READ_AHEAD_BYTES); | ||
770 | |||
771 | for (i=0 ; i < retlen ; i+=4) { | ||
772 | /* buffers MUST match, double word for word! */ | ||
773 | if(*((__u32 *) &read_buf1[i]) != | ||
774 | *((__u32 *) &read_buf2[i]) | ||
775 | ){ | ||
776 | /* flipping bits detected, time to erase sector */ | ||
777 | /* This will help us log some statistics etc. */ | ||
778 | D1(printk("Flipping bits detected in re-read round:%i of %i\n", | ||
779 | cnt, NUM_REREADS)); | ||
780 | D1(printk("check_partly_erased_sectors:flipping bits detected" | ||
781 | " @offset:0x%x(0x%x!=0x%x)\n", | ||
782 | (__u32)pos+i, *((__u32 *) &read_buf1[i]), | ||
783 | *((__u32 *) &read_buf2[i]))); | ||
784 | |||
785 | /* calculate start of present sector */ | ||
786 | offset = (((__u32)pos+i)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size; | ||
787 | |||
788 | D1(printk("check_partly_erased_sector():erasing sector starting 0x%x.\n", | ||
789 | offset)); | ||
790 | |||
791 | if (flash_erase_region(fmc->mtd, | ||
792 | offset, fmc->sector_size) < 0) { | ||
793 | printk(KERN_ERR "JFFS: Erase of flash failed. " | ||
794 | "offset = %u, erase_size = %d\n", | ||
795 | offset , fmc->sector_size); | ||
796 | |||
797 | err = -EIO; | ||
798 | goto returnBack; | ||
799 | |||
800 | }else{ | ||
801 | D1(printk("JFFS: Erase of flash sector @0x%x successful.\n", | ||
802 | offset)); | ||
803 | /* skip ahead to the next sector */ | ||
804 | pos = (((__u32)pos+i)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size; | ||
805 | pos += fmc->sector_size; | ||
806 | goto CHECK_NEXT; | ||
807 | } | ||
808 | } | ||
809 | } | ||
810 | } | ||
811 | pos += READ_AHEAD_BYTES; | ||
812 | } | ||
813 | |||
814 | returnBack: | ||
815 | kfree(read_buf1); | ||
816 | kfree(read_buf2); | ||
817 | |||
818 | D2(printk("check_partly_erased_sector():Done checking all sectors till offset 0x%x for flipping bits.\n", | ||
819 | (__u32)pos)); | ||
820 | |||
821 | return err; | ||
822 | |||
823 | }/* end check_partly_erased_sectors() */ | ||
824 | |||
825 | |||
826 | |||
827 | /* Scan the whole flash memory in order to find all nodes in the | ||
828 | file systems. */ | ||
829 | static int | ||
830 | jffs_scan_flash(struct jffs_control *c) | ||
831 | { | ||
832 | char name[JFFS_MAX_NAME_LEN + 2]; | ||
833 | struct jffs_raw_inode raw_inode; | ||
834 | struct jffs_node *node = NULL; | ||
835 | struct jffs_fmcontrol *fmc = c->fmc; | ||
836 | __u32 checksum; | ||
837 | __u8 tmp_accurate; | ||
838 | __u16 tmp_chksum; | ||
839 | __u32 deleted_file; | ||
840 | loff_t pos = 0; | ||
841 | loff_t start; | ||
842 | loff_t test_start; | ||
843 | loff_t end = fmc->flash_size; | ||
844 | __u8 *read_buf; | ||
845 | int i, len, retlen; | ||
846 | __u32 offset; | ||
847 | |||
848 | __u32 free_chunk_size1; | ||
849 | __u32 free_chunk_size2; | ||
850 | |||
851 | |||
852 | #define NUMFREEALLOWED 2 /* 2 chunks of at least erase size space allowed */ | ||
853 | int num_free_space = 0; /* Flag err if more than TWO | ||
854 | free blocks found. This is NOT allowed | ||
855 | by the current jffs design. | ||
856 | */ | ||
857 | int num_free_spc_not_accp = 0; /* For debugging purposed keep count | ||
858 | of how much free space was rejected and | ||
859 | marked dirty | ||
860 | */ | ||
861 | |||
862 | D1(printk("jffs_scan_flash(): start pos = 0x%lx, end = 0x%lx\n", | ||
863 | (long)pos, (long)end)); | ||
864 | |||
865 | flash_safe_acquire(fmc->mtd); | ||
866 | |||
867 | /* | ||
868 | check and make sure that any sector does not suffer | ||
869 | from the "partly erased, bit flipping syndrome" (TM Vipin :) | ||
870 | If so, offending sectors will be erased. | ||
871 | */ | ||
872 | if(check_partly_erased_sectors(fmc) < 0){ | ||
873 | |||
874 | flash_safe_release(fmc->mtd); | ||
875 | return -EIO; /* bad, bad, bad error. Cannot continue.*/ | ||
876 | } | ||
877 | |||
878 | /* Allocate read buffer */ | ||
879 | read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL); | ||
880 | if (!read_buf) { | ||
881 | flash_safe_release(fmc->mtd); | ||
882 | return -ENOMEM; | ||
883 | } | ||
884 | |||
885 | /* Start the scan. */ | ||
886 | while (pos < end) { | ||
887 | deleted_file = 0; | ||
888 | |||
889 | /* Remember the position from where we started this scan. */ | ||
890 | start = pos; | ||
891 | |||
892 | switch (flash_read_u32(fmc->mtd, pos)) { | ||
893 | case JFFS_EMPTY_BITMASK: | ||
894 | /* We have found 0xffffffff at this position. We have to | ||
895 | scan the rest of the flash till the end or till | ||
896 | something else than 0xffffffff is found. | ||
897 | Keep going till we do not find JFFS_EMPTY_BITMASK | ||
898 | anymore */ | ||
899 | |||
900 | D1(printk("jffs_scan_flash(): 0xffffffff at pos 0x%lx.\n", | ||
901 | (long)pos)); | ||
902 | |||
903 | while(pos < end){ | ||
904 | |||
905 | len = end - pos < 4096 ? end - pos : 4096; | ||
906 | |||
907 | retlen = flash_safe_read(fmc->mtd, pos, | ||
908 | &read_buf[0], len); | ||
909 | |||
910 | retlen &= ~3; | ||
911 | |||
912 | for (i=0 ; i < retlen ; i+=4, pos += 4) { | ||
913 | if(*((__u32 *) &read_buf[i]) != | ||
914 | JFFS_EMPTY_BITMASK) | ||
915 | break; | ||
916 | } | ||
917 | if (i == retlen) | ||
918 | continue; | ||
919 | else | ||
920 | break; | ||
921 | } | ||
922 | |||
923 | D1(printk("jffs_scan_flash():0xffffffff ended at pos 0x%lx.\n", | ||
924 | (long)pos)); | ||
925 | |||
926 | /* If some free space ends in the middle of a sector, | ||
927 | treat it as dirty rather than clean. | ||
928 | This is to handle the case where one thread | ||
929 | allocated space for a node, but didn't get to | ||
930 | actually _write_ it before power was lost, leaving | ||
931 | a gap in the log. Shifting all node writes into | ||
932 | a single kernel thread will fix the original problem. | ||
933 | */ | ||
934 | if ((__u32) pos % fmc->sector_size) { | ||
935 | /* If there was free space in previous | ||
936 | sectors, don't mark that dirty too - | ||
937 | only from the beginning of this sector | ||
938 | (or from start) | ||
939 | */ | ||
940 | |||
941 | test_start = pos & ~(fmc->sector_size-1); /* end of last sector */ | ||
942 | |||
943 | if (start < test_start) { | ||
944 | |||
945 | /* free space started in the previous sector! */ | ||
946 | |||
947 | if((num_free_space < NUMFREEALLOWED) && | ||
948 | ((unsigned int)(test_start - start) >= fmc->sector_size)){ | ||
949 | |||
950 | /* | ||
951 | Count it in if we are still under NUMFREEALLOWED *and* it is | ||
952 | at least 1 erase sector in length. This will keep us from | ||
953 | picking any little ole' space as "free". | ||
954 | */ | ||
955 | |||
956 | D1(printk("Reducing end of free space to 0x%x from 0x%x\n", | ||
957 | (unsigned int)test_start, (unsigned int)pos)); | ||
958 | |||
959 | D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n", | ||
960 | (unsigned int) start, | ||
961 | (unsigned int)(test_start - start))); | ||
962 | |||
963 | /* below, space from "start" to "pos" will be marked dirty. */ | ||
964 | start = test_start; | ||
965 | |||
966 | /* Being in here means that we have found at least an entire | ||
967 | erase sector size of free space ending on a sector boundary. | ||
968 | Keep track of free spaces accepted. | ||
969 | */ | ||
970 | num_free_space++; | ||
971 | }else{ | ||
972 | num_free_spc_not_accp++; | ||
973 | D1(printk("Free space (#%i) found but *Not* accepted: Starting" | ||
974 | " 0x%x for 0x%x bytes\n", | ||
975 | num_free_spc_not_accp, (unsigned int)start, | ||
976 | (unsigned int)((unsigned int)(pos & ~(fmc->sector_size-1)) - (unsigned int)start))); | ||
977 | |||
978 | } | ||
979 | |||
980 | } | ||
981 | if((((__u32)(pos - start)) != 0)){ | ||
982 | |||
983 | D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n", | ||
984 | (unsigned int) start, (unsigned int) (pos - start))); | ||
985 | jffs_fmalloced(fmc, (__u32) start, | ||
986 | (__u32) (pos - start), NULL); | ||
987 | }else{ | ||
988 | /* "Flipping bits" detected. This means that our scan for them | ||
989 | did not catch this offset. See check_partly_erased_sectors() for | ||
990 | more info. | ||
991 | */ | ||
992 | |||
993 | D1(printk("jffs_scan_flash():wants to allocate dirty flash " | ||
994 | "space for 0 bytes.\n")); | ||
995 | D1(printk("jffs_scan_flash(): Flipping bits! We will free " | ||
996 | "all allocated memory, erase this sector and remount\n")); | ||
997 | |||
998 | /* calculate start of present sector */ | ||
999 | offset = (((__u32)pos)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size; | ||
1000 | |||
1001 | D1(printk("jffs_scan_flash():erasing sector starting 0x%x.\n", | ||
1002 | offset)); | ||
1003 | |||
1004 | if (flash_erase_region(fmc->mtd, | ||
1005 | offset, fmc->sector_size) < 0) { | ||
1006 | printk(KERN_ERR "JFFS: Erase of flash failed. " | ||
1007 | "offset = %u, erase_size = %d\n", | ||
1008 | offset , fmc->sector_size); | ||
1009 | |||
1010 | flash_safe_release(fmc->mtd); | ||
1011 | kfree(read_buf); | ||
1012 | return -1; /* bad, bad, bad! */ | ||
1013 | |||
1014 | } | ||
1015 | flash_safe_release(fmc->mtd); | ||
1016 | kfree(read_buf); | ||
1017 | |||
1018 | return -EAGAIN; /* erased offending sector. Try mount one more time please. */ | ||
1019 | } | ||
1020 | }else{ | ||
1021 | /* Being in here means that we have found free space that ends on an erase sector | ||
1022 | boundary. | ||
1023 | Count it in if we are still under NUMFREEALLOWED *and* it is at least 1 erase | ||
1024 | sector in length. This will keep us from picking any little ole' space as "free". | ||
1025 | */ | ||
1026 | if((num_free_space < NUMFREEALLOWED) && | ||
1027 | ((unsigned int)(pos - start) >= fmc->sector_size)){ | ||
1028 | /* We really don't do anything to mark space as free, except *not* | ||
1029 | mark it dirty and just advance the "pos" location pointer. | ||
1030 | It will automatically be picked up as free space. | ||
1031 | */ | ||
1032 | num_free_space++; | ||
1033 | D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n", | ||
1034 | (unsigned int) start, (unsigned int) (pos - start))); | ||
1035 | }else{ | ||
1036 | num_free_spc_not_accp++; | ||
1037 | D1(printk("Free space (#%i) found but *Not* accepted: Starting " | ||
1038 | "0x%x for 0x%x bytes\n", num_free_spc_not_accp, | ||
1039 | (unsigned int) start, | ||
1040 | (unsigned int) (pos - start))); | ||
1041 | |||
1042 | /* Mark this space as dirty. We already have our free space. */ | ||
1043 | D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n", | ||
1044 | (unsigned int) start, (unsigned int) (pos - start))); | ||
1045 | jffs_fmalloced(fmc, (__u32) start, | ||
1046 | (__u32) (pos - start), NULL); | ||
1047 | } | ||
1048 | |||
1049 | } | ||
1050 | if(num_free_space > NUMFREEALLOWED){ | ||
1051 | printk(KERN_WARNING "jffs_scan_flash(): Found free space " | ||
1052 | "number %i. Only %i free space is allowed.\n", | ||
1053 | num_free_space, NUMFREEALLOWED); | ||
1054 | } | ||
1055 | continue; | ||
1056 | |||
1057 | case JFFS_DIRTY_BITMASK: | ||
1058 | /* We have found 0x00000000 at this position. Scan as far | ||
1059 | as possible to find out how much is dirty. */ | ||
1060 | D1(printk("jffs_scan_flash(): 0x00000000 at pos 0x%lx.\n", | ||
1061 | (long)pos)); | ||
1062 | for (; pos < end | ||
1063 | && JFFS_DIRTY_BITMASK == flash_read_u32(fmc->mtd, pos); | ||
1064 | pos += 4); | ||
1065 | D1(printk("jffs_scan_flash(): 0x00 ended at " | ||
1066 | "pos 0x%lx.\n", (long)pos)); | ||
1067 | jffs_fmalloced(fmc, (__u32) start, | ||
1068 | (__u32) (pos - start), NULL); | ||
1069 | continue; | ||
1070 | |||
1071 | case JFFS_MAGIC_BITMASK: | ||
1072 | /* We have probably found a new raw inode. */ | ||
1073 | break; | ||
1074 | |||
1075 | default: | ||
1076 | bad_inode: | ||
1077 | /* We're f*cked. This is not solved yet. We have | ||
1078 | to scan for the magic pattern. */ | ||
1079 | D1(printk("*************** Dirty flash memory or " | ||
1080 | "bad inode: " | ||
1081 | "hexdump(pos = 0x%lx, len = 128):\n", | ||
1082 | (long)pos)); | ||
1083 | D1(jffs_hexdump(fmc->mtd, pos, 128)); | ||
1084 | |||
1085 | for (pos += 4; pos < end; pos += 4) { | ||
1086 | switch (flash_read_u32(fmc->mtd, pos)) { | ||
1087 | case JFFS_MAGIC_BITMASK: | ||
1088 | case JFFS_EMPTY_BITMASK: | ||
1089 | /* handle these in the main switch() loop */ | ||
1090 | goto cont_scan; | ||
1091 | |||
1092 | default: | ||
1093 | break; | ||
1094 | } | ||
1095 | } | ||
1096 | |||
1097 | cont_scan: | ||
1098 | /* First, mark as dirty the region | ||
1099 | which really does contain crap. */ | ||
1100 | jffs_fmalloced(fmc, (__u32) start, | ||
1101 | (__u32) (pos - start), | ||
1102 | NULL); | ||
1103 | |||
1104 | continue; | ||
1105 | }/* switch */ | ||
1106 | |||
1107 | /* We have found the beginning of an inode. Create a | ||
1108 | node for it unless there already is one available. */ | ||
1109 | if (!node) { | ||
1110 | if (!(node = jffs_alloc_node())) { | ||
1111 | /* Free read buffer */ | ||
1112 | kfree(read_buf); | ||
1113 | |||
1114 | /* Release the flash device */ | ||
1115 | flash_safe_release(fmc->mtd); | ||
1116 | |||
1117 | return -ENOMEM; | ||
1118 | } | ||
1119 | DJM(no_jffs_node++); | ||
1120 | } | ||
1121 | |||
1122 | /* Read the next raw inode. */ | ||
1123 | |||
1124 | flash_safe_read(fmc->mtd, pos, (u_char *) &raw_inode, | ||
1125 | sizeof(struct jffs_raw_inode)); | ||
1126 | |||
1127 | /* When we compute the checksum for the inode, we never | ||
1128 | count the 'accurate' or the 'checksum' fields. */ | ||
1129 | tmp_accurate = raw_inode.accurate; | ||
1130 | tmp_chksum = raw_inode.chksum; | ||
1131 | raw_inode.accurate = 0; | ||
1132 | raw_inode.chksum = 0; | ||
1133 | checksum = jffs_checksum(&raw_inode, | ||
1134 | sizeof(struct jffs_raw_inode)); | ||
1135 | raw_inode.accurate = tmp_accurate; | ||
1136 | raw_inode.chksum = tmp_chksum; | ||
1137 | |||
1138 | D3(printk("*** We have found this raw inode at pos 0x%lx " | ||
1139 | "on the flash:\n", (long)pos)); | ||
1140 | D3(jffs_print_raw_inode(&raw_inode)); | ||
1141 | |||
1142 | if (checksum != raw_inode.chksum) { | ||
1143 | D1(printk("jffs_scan_flash(): Bad checksum: " | ||
1144 | "checksum = %u, " | ||
1145 | "raw_inode.chksum = %u\n", | ||
1146 | checksum, raw_inode.chksum)); | ||
1147 | pos += sizeof(struct jffs_raw_inode); | ||
1148 | jffs_fmalloced(fmc, (__u32) start, | ||
1149 | (__u32) (pos - start), NULL); | ||
1150 | /* Reuse this unused struct jffs_node. */ | ||
1151 | continue; | ||
1152 | } | ||
1153 | |||
1154 | /* Check the raw inode read so far. Start with the | ||
1155 | maximum length of the filename. */ | ||
1156 | if (raw_inode.nsize > JFFS_MAX_NAME_LEN) { | ||
1157 | printk(KERN_WARNING "jffs_scan_flash: Found a " | ||
1158 | "JFFS node with name too large\n"); | ||
1159 | goto bad_inode; | ||
1160 | } | ||
1161 | |||
1162 | if (raw_inode.rename && raw_inode.dsize != sizeof(__u32)) { | ||
1163 | printk(KERN_WARNING "jffs_scan_flash: Found a " | ||
1164 | "rename node with dsize %u.\n", | ||
1165 | raw_inode.dsize); | ||
1166 | jffs_print_raw_inode(&raw_inode); | ||
1167 | goto bad_inode; | ||
1168 | } | ||
1169 | |||
1170 | /* The node's data segment should not exceed a | ||
1171 | certain length. */ | ||
1172 | if (raw_inode.dsize > fmc->max_chunk_size) { | ||
1173 | printk(KERN_WARNING "jffs_scan_flash: Found a " | ||
1174 | "JFFS node with dsize (0x%x) > max_chunk_size (0x%x)\n", | ||
1175 | raw_inode.dsize, fmc->max_chunk_size); | ||
1176 | goto bad_inode; | ||
1177 | } | ||
1178 | |||
1179 | pos += sizeof(struct jffs_raw_inode); | ||
1180 | |||
1181 | /* This shouldn't be necessary because a node that | ||
1182 | violates the flash boundaries shouldn't be written | ||
1183 | in the first place. */ | ||
1184 | if (pos >= end) { | ||
1185 | goto check_node; | ||
1186 | } | ||
1187 | |||
1188 | /* Read the name. */ | ||
1189 | *name = 0; | ||
1190 | if (raw_inode.nsize) { | ||
1191 | flash_safe_read(fmc->mtd, pos, name, raw_inode.nsize); | ||
1192 | name[raw_inode.nsize] = '\0'; | ||
1193 | pos += raw_inode.nsize | ||
1194 | + JFFS_GET_PAD_BYTES(raw_inode.nsize); | ||
1195 | D3(printk("name == \"%s\"\n", name)); | ||
1196 | checksum = jffs_checksum(name, raw_inode.nsize); | ||
1197 | if (checksum != raw_inode.nchksum) { | ||
1198 | D1(printk("jffs_scan_flash(): Bad checksum: " | ||
1199 | "checksum = %u, " | ||
1200 | "raw_inode.nchksum = %u\n", | ||
1201 | checksum, raw_inode.nchksum)); | ||
1202 | jffs_fmalloced(fmc, (__u32) start, | ||
1203 | (__u32) (pos - start), NULL); | ||
1204 | /* Reuse this unused struct jffs_node. */ | ||
1205 | continue; | ||
1206 | } | ||
1207 | if (pos >= end) { | ||
1208 | goto check_node; | ||
1209 | } | ||
1210 | } | ||
1211 | |||
1212 | /* Read the data, if it exists, in order to be sure it | ||
1213 | matches the checksum. */ | ||
1214 | if (raw_inode.dsize) { | ||
1215 | if (raw_inode.rename) { | ||
1216 | deleted_file = flash_read_u32(fmc->mtd, pos); | ||
1217 | } | ||
1218 | if (jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize, &checksum)) { | ||
1219 | printk("jffs_checksum_flash() failed to calculate a checksum\n"); | ||
1220 | jffs_fmalloced(fmc, (__u32) start, | ||
1221 | (__u32) (pos - start), NULL); | ||
1222 | /* Reuse this unused struct jffs_node. */ | ||
1223 | continue; | ||
1224 | } | ||
1225 | pos += raw_inode.dsize | ||
1226 | + JFFS_GET_PAD_BYTES(raw_inode.dsize); | ||
1227 | |||
1228 | if (checksum != raw_inode.dchksum) { | ||
1229 | D1(printk("jffs_scan_flash(): Bad checksum: " | ||
1230 | "checksum = %u, " | ||
1231 | "raw_inode.dchksum = %u\n", | ||
1232 | checksum, raw_inode.dchksum)); | ||
1233 | jffs_fmalloced(fmc, (__u32) start, | ||
1234 | (__u32) (pos - start), NULL); | ||
1235 | /* Reuse this unused struct jffs_node. */ | ||
1236 | continue; | ||
1237 | } | ||
1238 | } | ||
1239 | |||
1240 | check_node: | ||
1241 | |||
1242 | /* Remember the highest inode number in the whole file | ||
1243 | system. This information will be used when assigning | ||
1244 | new files new inode numbers. */ | ||
1245 | if (c->next_ino <= raw_inode.ino) { | ||
1246 | c->next_ino = raw_inode.ino + 1; | ||
1247 | } | ||
1248 | |||
1249 | if (raw_inode.accurate) { | ||
1250 | int err; | ||
1251 | node->data_offset = raw_inode.offset; | ||
1252 | node->data_size = raw_inode.dsize; | ||
1253 | node->removed_size = raw_inode.rsize; | ||
1254 | /* Compute the offset to the actual data in the | ||
1255 | on-flash node. */ | ||
1256 | node->fm_offset | ||
1257 | = sizeof(struct jffs_raw_inode) | ||
1258 | + raw_inode.nsize | ||
1259 | + JFFS_GET_PAD_BYTES(raw_inode.nsize); | ||
1260 | node->fm = jffs_fmalloced(fmc, (__u32) start, | ||
1261 | (__u32) (pos - start), | ||
1262 | node); | ||
1263 | if (!node->fm) { | ||
1264 | D(printk("jffs_scan_flash(): !node->fm\n")); | ||
1265 | jffs_free_node(node); | ||
1266 | DJM(no_jffs_node--); | ||
1267 | |||
1268 | /* Free read buffer */ | ||
1269 | kfree(read_buf); | ||
1270 | |||
1271 | /* Release the flash device */ | ||
1272 | flash_safe_release(fmc->mtd); | ||
1273 | |||
1274 | return -ENOMEM; | ||
1275 | } | ||
1276 | if ((err = jffs_insert_node(c, NULL, &raw_inode, | ||
1277 | name, node)) < 0) { | ||
1278 | printk("JFFS: Failed to handle raw inode. " | ||
1279 | "(err = %d)\n", err); | ||
1280 | break; | ||
1281 | } | ||
1282 | if (raw_inode.rename) { | ||
1283 | struct jffs_delete_list *dl | ||
1284 | = (struct jffs_delete_list *) | ||
1285 | kmalloc(sizeof(struct jffs_delete_list), | ||
1286 | GFP_KERNEL); | ||
1287 | if (!dl) { | ||
1288 | D(printk("jffs_scan_flash: !dl\n")); | ||
1289 | jffs_free_node(node); | ||
1290 | DJM(no_jffs_node--); | ||
1291 | |||
1292 | /* Release the flash device */ | ||
1293 | flash_safe_release(fmc->flash_part); | ||
1294 | |||
1295 | /* Free read buffer */ | ||
1296 | kfree(read_buf); | ||
1297 | |||
1298 | return -ENOMEM; | ||
1299 | } | ||
1300 | dl->ino = deleted_file; | ||
1301 | dl->next = c->delete_list; | ||
1302 | c->delete_list = dl; | ||
1303 | node->data_size = 0; | ||
1304 | } | ||
1305 | D3(jffs_print_node(node)); | ||
1306 | node = NULL; /* Don't free the node! */ | ||
1307 | } | ||
1308 | else { | ||
1309 | jffs_fmalloced(fmc, (__u32) start, | ||
1310 | (__u32) (pos - start), NULL); | ||
1311 | D3(printk("jffs_scan_flash(): Just found an obsolete " | ||
1312 | "raw_inode. Continuing the scan...\n")); | ||
1313 | /* Reuse this unused struct jffs_node. */ | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1317 | if (node) { | ||
1318 | jffs_free_node(node); | ||
1319 | DJM(no_jffs_node--); | ||
1320 | } | ||
1321 | jffs_build_end(fmc); | ||
1322 | |||
1323 | /* Free read buffer */ | ||
1324 | kfree(read_buf); | ||
1325 | |||
1326 | if(!num_free_space){ | ||
1327 | printk(KERN_WARNING "jffs_scan_flash(): Did not find even a single " | ||
1328 | "chunk of free space. This is BAD!\n"); | ||
1329 | } | ||
1330 | |||
1331 | /* Return happy */ | ||
1332 | D3(printk("jffs_scan_flash(): Leaving...\n")); | ||
1333 | flash_safe_release(fmc->mtd); | ||
1334 | |||
1335 | /* This is to trap the "free size accounting screwed error. */ | ||
1336 | free_chunk_size1 = jffs_free_size1(fmc); | ||
1337 | free_chunk_size2 = jffs_free_size2(fmc); | ||
1338 | |||
1339 | if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) { | ||
1340 | |||
1341 | printk(KERN_WARNING "jffs_scan_falsh():Free size accounting screwed\n"); | ||
1342 | printk(KERN_WARNING "jfffs_scan_flash():free_chunk_size1 == 0x%x, " | ||
1343 | "free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", | ||
1344 | free_chunk_size1, free_chunk_size2, fmc->free_size); | ||
1345 | |||
1346 | return -1; /* Do NOT mount f/s so that we can inspect what happened. | ||
1347 | Mounting this screwed up f/s will screw us up anyway. | ||
1348 | */ | ||
1349 | } | ||
1350 | |||
1351 | return 0; /* as far as we are concerned, we are happy! */ | ||
1352 | } /* jffs_scan_flash() */ | ||
1353 | |||
1354 | |||
1355 | /* Insert any kind of node into the file system. Take care of data | ||
1356 | insertions and deletions. Also remove redundant information. The | ||
1357 | memory allocated for the `name' is regarded as "given away" in the | ||
1358 | caller's perspective. */ | ||
1359 | int | ||
1360 | jffs_insert_node(struct jffs_control *c, struct jffs_file *f, | ||
1361 | const struct jffs_raw_inode *raw_inode, | ||
1362 | const char *name, struct jffs_node *node) | ||
1363 | { | ||
1364 | int update_name = 0; | ||
1365 | int insert_into_tree = 0; | ||
1366 | |||
1367 | D2(printk("jffs_insert_node(): ino = %u, version = %u, " | ||
1368 | "name = \"%s\", deleted = %d\n", | ||
1369 | raw_inode->ino, raw_inode->version, | ||
1370 | ((name && *name) ? name : ""), raw_inode->deleted)); | ||
1371 | |||
1372 | /* If there doesn't exist an associated jffs_file, then | ||
1373 | create, initialize and insert one into the file system. */ | ||
1374 | if (!f && !(f = jffs_find_file(c, raw_inode->ino))) { | ||
1375 | if (!(f = jffs_create_file(c, raw_inode))) { | ||
1376 | return -ENOMEM; | ||
1377 | } | ||
1378 | jffs_insert_file_into_hash(f); | ||
1379 | insert_into_tree = 1; | ||
1380 | } | ||
1381 | node->ino = raw_inode->ino; | ||
1382 | node->version = raw_inode->version; | ||
1383 | node->data_size = raw_inode->dsize; | ||
1384 | node->fm_offset = sizeof(struct jffs_raw_inode) + raw_inode->nsize | ||
1385 | + JFFS_GET_PAD_BYTES(raw_inode->nsize); | ||
1386 | node->name_size = raw_inode->nsize; | ||
1387 | |||
1388 | /* Now insert the node at the correct position into the file's | ||
1389 | version list. */ | ||
1390 | if (!f->version_head) { | ||
1391 | /* This is the first node. */ | ||
1392 | f->version_head = node; | ||
1393 | f->version_tail = node; | ||
1394 | node->version_prev = NULL; | ||
1395 | node->version_next = NULL; | ||
1396 | f->highest_version = node->version; | ||
1397 | update_name = 1; | ||
1398 | f->mode = raw_inode->mode; | ||
1399 | f->uid = raw_inode->uid; | ||
1400 | f->gid = raw_inode->gid; | ||
1401 | f->atime = raw_inode->atime; | ||
1402 | f->mtime = raw_inode->mtime; | ||
1403 | f->ctime = raw_inode->ctime; | ||
1404 | } | ||
1405 | else if ((f->highest_version < node->version) | ||
1406 | || (node->version == 0)) { | ||
1407 | /* Insert at the end of the list. I.e. this node is the | ||
1408 | newest one so far. */ | ||
1409 | node->version_prev = f->version_tail; | ||
1410 | node->version_next = NULL; | ||
1411 | f->version_tail->version_next = node; | ||
1412 | f->version_tail = node; | ||
1413 | f->highest_version = node->version; | ||
1414 | update_name = 1; | ||
1415 | f->pino = raw_inode->pino; | ||
1416 | f->mode = raw_inode->mode; | ||
1417 | f->uid = raw_inode->uid; | ||
1418 | f->gid = raw_inode->gid; | ||
1419 | f->atime = raw_inode->atime; | ||
1420 | f->mtime = raw_inode->mtime; | ||
1421 | f->ctime = raw_inode->ctime; | ||
1422 | } | ||
1423 | else if (f->version_head->version > node->version) { | ||
1424 | /* Insert at the bottom of the list. */ | ||
1425 | node->version_prev = NULL; | ||
1426 | node->version_next = f->version_head; | ||
1427 | f->version_head->version_prev = node; | ||
1428 | f->version_head = node; | ||
1429 | if (!f->name) { | ||
1430 | update_name = 1; | ||
1431 | } | ||
1432 | } | ||
1433 | else { | ||
1434 | struct jffs_node *n; | ||
1435 | int newer_name = 0; | ||
1436 | /* Search for the insertion position starting from | ||
1437 | the tail (newest node). */ | ||
1438 | for (n = f->version_tail; n; n = n->version_prev) { | ||
1439 | if (n->version < node->version) { | ||
1440 | node->version_prev = n; | ||
1441 | node->version_next = n->version_next; | ||
1442 | node->version_next->version_prev = node; | ||
1443 | n->version_next = node; | ||
1444 | if (!newer_name) { | ||
1445 | update_name = 1; | ||
1446 | } | ||
1447 | break; | ||
1448 | } | ||
1449 | if (n->name_size) { | ||
1450 | newer_name = 1; | ||
1451 | } | ||
1452 | } | ||
1453 | } | ||
1454 | |||
1455 | /* Deletion is irreversible. If any 'deleted' node is ever | ||
1456 | written, the file is deleted */ | ||
1457 | if (raw_inode->deleted) | ||
1458 | f->deleted = raw_inode->deleted; | ||
1459 | |||
1460 | /* Perhaps update the name. */ | ||
1461 | if (raw_inode->nsize && update_name && name && *name && (name != f->name)) { | ||
1462 | if (f->name) { | ||
1463 | kfree(f->name); | ||
1464 | DJM(no_name--); | ||
1465 | } | ||
1466 | if (!(f->name = kmalloc(raw_inode->nsize + 1, | ||
1467 | GFP_KERNEL))) { | ||
1468 | return -ENOMEM; | ||
1469 | } | ||
1470 | DJM(no_name++); | ||
1471 | memcpy(f->name, name, raw_inode->nsize); | ||
1472 | f->name[raw_inode->nsize] = '\0'; | ||
1473 | f->nsize = raw_inode->nsize; | ||
1474 | D3(printk("jffs_insert_node(): Updated the name of " | ||
1475 | "the file to \"%s\".\n", name)); | ||
1476 | } | ||
1477 | |||
1478 | if (!c->building_fs) { | ||
1479 | D3(printk("jffs_insert_node(): ---------------------------" | ||
1480 | "------------------------------------------- 1\n")); | ||
1481 | if (insert_into_tree) { | ||
1482 | jffs_insert_file_into_tree(f); | ||
1483 | } | ||
1484 | /* Once upon a time, we would call jffs_possibly_delete_file() | ||
1485 | here. That causes an oops if someone's still got the file | ||
1486 | open, so now we only do it in jffs_delete_inode() | ||
1487 | -- dwmw2 | ||
1488 | */ | ||
1489 | if (node->data_size || node->removed_size) { | ||
1490 | jffs_update_file(f, node); | ||
1491 | } | ||
1492 | jffs_remove_redundant_nodes(f); | ||
1493 | |||
1494 | jffs_garbage_collect_trigger(c); | ||
1495 | |||
1496 | D3(printk("jffs_insert_node(): ---------------------------" | ||
1497 | "------------------------------------------- 2\n")); | ||
1498 | } | ||
1499 | |||
1500 | return 0; | ||
1501 | } /* jffs_insert_node() */ | ||
1502 | |||
1503 | |||
1504 | /* Unlink a jffs_node from the version list it is in. */ | ||
1505 | static inline void | ||
1506 | jffs_unlink_node_from_version_list(struct jffs_file *f, | ||
1507 | struct jffs_node *node) | ||
1508 | { | ||
1509 | if (node->version_prev) { | ||
1510 | node->version_prev->version_next = node->version_next; | ||
1511 | } else { | ||
1512 | f->version_head = node->version_next; | ||
1513 | } | ||
1514 | if (node->version_next) { | ||
1515 | node->version_next->version_prev = node->version_prev; | ||
1516 | } else { | ||
1517 | f->version_tail = node->version_prev; | ||
1518 | } | ||
1519 | } | ||
1520 | |||
1521 | |||
1522 | /* Unlink a jffs_node from the range list it is in. */ | ||
1523 | static inline void | ||
1524 | jffs_unlink_node_from_range_list(struct jffs_file *f, struct jffs_node *node) | ||
1525 | { | ||
1526 | if (node->range_prev) { | ||
1527 | node->range_prev->range_next = node->range_next; | ||
1528 | } | ||
1529 | else { | ||
1530 | f->range_head = node->range_next; | ||
1531 | } | ||
1532 | if (node->range_next) { | ||
1533 | node->range_next->range_prev = node->range_prev; | ||
1534 | } | ||
1535 | else { | ||
1536 | f->range_tail = node->range_prev; | ||
1537 | } | ||
1538 | } | ||
1539 | |||
1540 | |||
1541 | /* Function used by jffs_remove_redundant_nodes() below. This function | ||
1542 | classifies what kind of information a node adds to a file. */ | ||
1543 | static inline __u8 | ||
1544 | jffs_classify_node(struct jffs_node *node) | ||
1545 | { | ||
1546 | __u8 mod_type = JFFS_MODIFY_INODE; | ||
1547 | |||
1548 | if (node->name_size) { | ||
1549 | mod_type |= JFFS_MODIFY_NAME; | ||
1550 | } | ||
1551 | if (node->data_size || node->removed_size) { | ||
1552 | mod_type |= JFFS_MODIFY_DATA; | ||
1553 | } | ||
1554 | return mod_type; | ||
1555 | } | ||
1556 | |||
1557 | |||
1558 | /* Remove redundant nodes from a file. Mark the on-flash memory | ||
1559 | as dirty. */ | ||
1560 | static int | ||
1561 | jffs_remove_redundant_nodes(struct jffs_file *f) | ||
1562 | { | ||
1563 | struct jffs_node *newest_node; | ||
1564 | struct jffs_node *cur; | ||
1565 | struct jffs_node *prev; | ||
1566 | __u8 newest_type; | ||
1567 | __u8 mod_type; | ||
1568 | __u8 node_with_name_later = 0; | ||
1569 | |||
1570 | if (!(newest_node = f->version_tail)) { | ||
1571 | return 0; | ||
1572 | } | ||
1573 | |||
1574 | /* What does the `newest_node' modify? */ | ||
1575 | newest_type = jffs_classify_node(newest_node); | ||
1576 | node_with_name_later = newest_type & JFFS_MODIFY_NAME; | ||
1577 | |||
1578 | D3(printk("jffs_remove_redundant_nodes(): ino: %u, name: \"%s\", " | ||
1579 | "newest_type: %u\n", f->ino, (f->name ? f->name : ""), | ||
1580 | newest_type)); | ||
1581 | |||
1582 | /* Traverse the file's nodes and determine which of them that are | ||
1583 | superfluous. Yeah, this might look very complex at first | ||
1584 | glance but it is actually very simple. */ | ||
1585 | for (cur = newest_node->version_prev; cur; cur = prev) { | ||
1586 | prev = cur->version_prev; | ||
1587 | mod_type = jffs_classify_node(cur); | ||
1588 | if ((mod_type <= JFFS_MODIFY_INODE) | ||
1589 | || ((newest_type & JFFS_MODIFY_NAME) | ||
1590 | && (mod_type | ||
1591 | <= (JFFS_MODIFY_INODE + JFFS_MODIFY_NAME))) | ||
1592 | || (cur->data_size == 0 && cur->removed_size | ||
1593 | && !cur->version_prev && node_with_name_later)) { | ||
1594 | /* Yes, this node is redundant. Remove it. */ | ||
1595 | D2(printk("jffs_remove_redundant_nodes(): " | ||
1596 | "Removing node: ino: %u, version: %u, " | ||
1597 | "mod_type: %u\n", cur->ino, cur->version, | ||
1598 | mod_type)); | ||
1599 | jffs_unlink_node_from_version_list(f, cur); | ||
1600 | jffs_fmfree(f->c->fmc, cur->fm, cur); | ||
1601 | jffs_free_node(cur); | ||
1602 | DJM(no_jffs_node--); | ||
1603 | } | ||
1604 | else { | ||
1605 | node_with_name_later |= (mod_type & JFFS_MODIFY_NAME); | ||
1606 | } | ||
1607 | } | ||
1608 | |||
1609 | return 0; | ||
1610 | } | ||
1611 | |||
1612 | |||
1613 | /* Insert a file into the hash table. */ | ||
1614 | static int | ||
1615 | jffs_insert_file_into_hash(struct jffs_file *f) | ||
1616 | { | ||
1617 | int i = f->ino % f->c->hash_len; | ||
1618 | |||
1619 | D3(printk("jffs_insert_file_into_hash(): f->ino: %u\n", f->ino)); | ||
1620 | |||
1621 | list_add(&f->hash, &f->c->hash[i]); | ||
1622 | return 0; | ||
1623 | } | ||
1624 | |||
1625 | |||
1626 | /* Insert a file into the file system tree. */ | ||
1627 | int | ||
1628 | jffs_insert_file_into_tree(struct jffs_file *f) | ||
1629 | { | ||
1630 | struct jffs_file *parent; | ||
1631 | |||
1632 | D3(printk("jffs_insert_file_into_tree(): name: \"%s\"\n", | ||
1633 | (f->name ? f->name : ""))); | ||
1634 | |||
1635 | if (!(parent = jffs_find_file(f->c, f->pino))) { | ||
1636 | if (f->pino == 0) { | ||
1637 | f->c->root = f; | ||
1638 | f->parent = NULL; | ||
1639 | f->sibling_prev = NULL; | ||
1640 | f->sibling_next = NULL; | ||
1641 | return 0; | ||
1642 | } | ||
1643 | else { | ||
1644 | D1(printk("jffs_insert_file_into_tree(): Found " | ||
1645 | "inode with no parent and pino == %u\n", | ||
1646 | f->pino)); | ||
1647 | return -1; | ||
1648 | } | ||
1649 | } | ||
1650 | f->parent = parent; | ||
1651 | f->sibling_next = parent->children; | ||
1652 | if (f->sibling_next) { | ||
1653 | f->sibling_next->sibling_prev = f; | ||
1654 | } | ||
1655 | f->sibling_prev = NULL; | ||
1656 | parent->children = f; | ||
1657 | return 0; | ||
1658 | } | ||
1659 | |||
1660 | |||
1661 | /* Remove a file from the hash table. */ | ||
1662 | static int | ||
1663 | jffs_unlink_file_from_hash(struct jffs_file *f) | ||
1664 | { | ||
1665 | D3(printk("jffs_unlink_file_from_hash(): f: 0x%p, " | ||
1666 | "ino %u\n", f, f->ino)); | ||
1667 | |||
1668 | list_del(&f->hash); | ||
1669 | return 0; | ||
1670 | } | ||
1671 | |||
1672 | |||
1673 | /* Just remove the file from the parent's children. Don't free | ||
1674 | any memory. */ | ||
1675 | int | ||
1676 | jffs_unlink_file_from_tree(struct jffs_file *f) | ||
1677 | { | ||
1678 | D3(printk("jffs_unlink_file_from_tree(): ino: %d, pino: %d, name: " | ||
1679 | "\"%s\"\n", f->ino, f->pino, (f->name ? f->name : ""))); | ||
1680 | |||
1681 | if (f->sibling_prev) { | ||
1682 | f->sibling_prev->sibling_next = f->sibling_next; | ||
1683 | } | ||
1684 | else if (f->parent) { | ||
1685 | D3(printk("f->parent=%p\n", f->parent)); | ||
1686 | f->parent->children = f->sibling_next; | ||
1687 | } | ||
1688 | if (f->sibling_next) { | ||
1689 | f->sibling_next->sibling_prev = f->sibling_prev; | ||
1690 | } | ||
1691 | return 0; | ||
1692 | } | ||
1693 | |||
1694 | |||
1695 | /* Find a file with its inode number. */ | ||
1696 | struct jffs_file * | ||
1697 | jffs_find_file(struct jffs_control *c, __u32 ino) | ||
1698 | { | ||
1699 | struct jffs_file *f; | ||
1700 | int i = ino % c->hash_len; | ||
1701 | |||
1702 | D3(printk("jffs_find_file(): ino: %u\n", ino)); | ||
1703 | |||
1704 | list_for_each_entry(f, &c->hash[i], hash) { | ||
1705 | if (ino != f->ino) | ||
1706 | continue; | ||
1707 | D3(printk("jffs_find_file(): Found file with ino " | ||
1708 | "%u. (name: \"%s\")\n", | ||
1709 | ino, (f->name ? f->name : "")); | ||
1710 | ); | ||
1711 | return f; | ||
1712 | } | ||
1713 | D3(printk("jffs_find_file(): Didn't find file " | ||
1714 | "with ino %u.\n", ino); | ||
1715 | ); | ||
1716 | return NULL; | ||
1717 | } | ||
1718 | |||
1719 | |||
1720 | /* Find a file in a directory. We are comparing the names. */ | ||
1721 | struct jffs_file * | ||
1722 | jffs_find_child(struct jffs_file *dir, const char *name, int len) | ||
1723 | { | ||
1724 | struct jffs_file *f; | ||
1725 | |||
1726 | D3(printk("jffs_find_child()\n")); | ||
1727 | |||
1728 | for (f = dir->children; f; f = f->sibling_next) { | ||
1729 | if (!f->deleted && f->name | ||
1730 | && !strncmp(f->name, name, len) | ||
1731 | && f->name[len] == '\0') { | ||
1732 | break; | ||
1733 | } | ||
1734 | } | ||
1735 | |||
1736 | D3(if (f) { | ||
1737 | printk("jffs_find_child(): Found \"%s\".\n", f->name); | ||
1738 | } | ||
1739 | else { | ||
1740 | char *copy = kmalloc(len + 1, GFP_KERNEL); | ||
1741 | if (copy) { | ||
1742 | memcpy(copy, name, len); | ||
1743 | copy[len] = '\0'; | ||
1744 | } | ||
1745 | printk("jffs_find_child(): Didn't find the file \"%s\".\n", | ||
1746 | (copy ? copy : "")); | ||
1747 | kfree(copy); | ||
1748 | }); | ||
1749 | |||
1750 | return f; | ||
1751 | } | ||
1752 | |||
1753 | |||
1754 | /* Write a raw inode that takes up a certain amount of space in the flash | ||
1755 | memory. At the end of the flash device, there is often space that is | ||
1756 | impossible to use. At these times we want to mark this space as not | ||
1757 | used. In the cases when the amount of space is greater or equal than | ||
1758 | a struct jffs_raw_inode, we write a "dummy node" that takes up this | ||
1759 | space. The space after the raw inode, if it exists, is left as it is. | ||
1760 | Since this space after the raw inode contains JFFS_EMPTY_BITMASK bytes, | ||
1761 | we can compute the checksum of it; we don't have to manipulate it any | ||
1762 | further. | ||
1763 | |||
1764 | If the space left on the device is less than the size of a struct | ||
1765 | jffs_raw_inode, this space is filled with JFFS_DIRTY_BITMASK bytes. | ||
1766 | No raw inode is written this time. */ | ||
1767 | static int | ||
1768 | jffs_write_dummy_node(struct jffs_control *c, struct jffs_fm *dirty_fm) | ||
1769 | { | ||
1770 | struct jffs_fmcontrol *fmc = c->fmc; | ||
1771 | int err; | ||
1772 | |||
1773 | D1(printk("jffs_write_dummy_node(): dirty_fm->offset = 0x%08x, " | ||
1774 | "dirty_fm->size = %u\n", | ||
1775 | dirty_fm->offset, dirty_fm->size)); | ||
1776 | |||
1777 | if (dirty_fm->size >= sizeof(struct jffs_raw_inode)) { | ||
1778 | struct jffs_raw_inode raw_inode; | ||
1779 | memset(&raw_inode, 0, sizeof(struct jffs_raw_inode)); | ||
1780 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
1781 | raw_inode.dsize = dirty_fm->size | ||
1782 | - sizeof(struct jffs_raw_inode); | ||
1783 | raw_inode.dchksum = raw_inode.dsize * 0xff; | ||
1784 | raw_inode.chksum | ||
1785 | = jffs_checksum(&raw_inode, sizeof(struct jffs_raw_inode)); | ||
1786 | |||
1787 | if ((err = flash_safe_write(fmc->mtd, | ||
1788 | dirty_fm->offset, | ||
1789 | (u_char *)&raw_inode, | ||
1790 | sizeof(struct jffs_raw_inode))) | ||
1791 | < 0) { | ||
1792 | printk(KERN_ERR "JFFS: jffs_write_dummy_node: " | ||
1793 | "flash_safe_write failed!\n"); | ||
1794 | return err; | ||
1795 | } | ||
1796 | } | ||
1797 | else { | ||
1798 | flash_safe_acquire(fmc->mtd); | ||
1799 | flash_memset(fmc->mtd, dirty_fm->offset, 0, dirty_fm->size); | ||
1800 | flash_safe_release(fmc->mtd); | ||
1801 | } | ||
1802 | |||
1803 | D3(printk("jffs_write_dummy_node(): Leaving...\n")); | ||
1804 | return 0; | ||
1805 | } | ||
1806 | |||
1807 | |||
1808 | /* Write a raw inode, possibly its name and possibly some data. */ | ||
1809 | int | ||
1810 | jffs_write_node(struct jffs_control *c, struct jffs_node *node, | ||
1811 | struct jffs_raw_inode *raw_inode, | ||
1812 | const char *name, const unsigned char *data, | ||
1813 | int recoverable, | ||
1814 | struct jffs_file *f) | ||
1815 | { | ||
1816 | struct jffs_fmcontrol *fmc = c->fmc; | ||
1817 | struct jffs_fm *fm; | ||
1818 | struct kvec node_iovec[4]; | ||
1819 | unsigned long iovec_cnt; | ||
1820 | |||
1821 | __u32 pos; | ||
1822 | int err; | ||
1823 | __u32 slack = 0; | ||
1824 | |||
1825 | __u32 total_name_size = raw_inode->nsize | ||
1826 | + JFFS_GET_PAD_BYTES(raw_inode->nsize); | ||
1827 | __u32 total_data_size = raw_inode->dsize | ||
1828 | + JFFS_GET_PAD_BYTES(raw_inode->dsize); | ||
1829 | __u32 total_size = sizeof(struct jffs_raw_inode) | ||
1830 | + total_name_size + total_data_size; | ||
1831 | |||
1832 | /* If this node isn't something that will eventually let | ||
1833 | GC free even more space, then don't allow it unless | ||
1834 | there's at least max_chunk_size space still available | ||
1835 | */ | ||
1836 | if (!recoverable) | ||
1837 | slack = fmc->max_chunk_size; | ||
1838 | |||
1839 | |||
1840 | /* Fire the retrorockets and shoot the fruiton torpedoes, sir! */ | ||
1841 | |||
1842 | ASSERT(if (!node) { | ||
1843 | printk("jffs_write_node(): node == NULL\n"); | ||
1844 | return -EINVAL; | ||
1845 | }); | ||
1846 | ASSERT(if (raw_inode && raw_inode->nsize && !name) { | ||
1847 | printk("*** jffs_write_node(): nsize = %u but name == NULL\n", | ||
1848 | raw_inode->nsize); | ||
1849 | return -EINVAL; | ||
1850 | }); | ||
1851 | |||
1852 | D1(printk("jffs_write_node(): filename = \"%s\", ino = %u, " | ||
1853 | "total_size = %u\n", | ||
1854 | (name ? name : ""), raw_inode->ino, | ||
1855 | total_size)); | ||
1856 | |||
1857 | jffs_fm_write_lock(fmc); | ||
1858 | |||
1859 | retry: | ||
1860 | fm = NULL; | ||
1861 | err = 0; | ||
1862 | while (!fm) { | ||
1863 | |||
1864 | /* Deadlocks suck. */ | ||
1865 | while(fmc->free_size < fmc->min_free_size + total_size + slack) { | ||
1866 | jffs_fm_write_unlock(fmc); | ||
1867 | if (!JFFS_ENOUGH_SPACE(c, total_size + slack)) | ||
1868 | return -ENOSPC; | ||
1869 | jffs_fm_write_lock(fmc); | ||
1870 | } | ||
1871 | |||
1872 | /* First try to allocate some flash memory. */ | ||
1873 | err = jffs_fmalloc(fmc, total_size, node, &fm); | ||
1874 | |||
1875 | if (err == -ENOSPC) { | ||
1876 | /* Just out of space. GC and try again */ | ||
1877 | if (fmc->dirty_size < fmc->sector_size) { | ||
1878 | D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) " | ||
1879 | "failed, no dirty space to GC\n", fmc, | ||
1880 | total_size)); | ||
1881 | return err; | ||
1882 | } | ||
1883 | |||
1884 | D1(printk(KERN_INFO "jffs_write_node(): Calling jffs_garbage_collect_now()\n")); | ||
1885 | jffs_fm_write_unlock(fmc); | ||
1886 | if ((err = jffs_garbage_collect_now(c))) { | ||
1887 | D(printk("jffs_write_node(): jffs_garbage_collect_now() failed\n")); | ||
1888 | return err; | ||
1889 | } | ||
1890 | jffs_fm_write_lock(fmc); | ||
1891 | continue; | ||
1892 | } | ||
1893 | |||
1894 | if (err < 0) { | ||
1895 | jffs_fm_write_unlock(fmc); | ||
1896 | |||
1897 | D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) " | ||
1898 | "failed!\n", fmc, total_size)); | ||
1899 | return err; | ||
1900 | } | ||
1901 | |||
1902 | if (!fm->nodes) { | ||
1903 | /* The jffs_fm struct that we got is not good enough. | ||
1904 | Make that space dirty and try again */ | ||
1905 | if ((err = jffs_write_dummy_node(c, fm)) < 0) { | ||
1906 | kfree(fm); | ||
1907 | DJM(no_jffs_fm--); | ||
1908 | jffs_fm_write_unlock(fmc); | ||
1909 | D(printk("jffs_write_node(): " | ||
1910 | "jffs_write_dummy_node(): Failed!\n")); | ||
1911 | return err; | ||
1912 | } | ||
1913 | fm = NULL; | ||
1914 | } | ||
1915 | } /* while(!fm) */ | ||
1916 | node->fm = fm; | ||
1917 | |||
1918 | ASSERT(if (fm->nodes == 0) { | ||
1919 | printk(KERN_ERR "jffs_write_node(): fm->nodes == 0\n"); | ||
1920 | }); | ||
1921 | |||
1922 | pos = node->fm->offset; | ||
1923 | |||
1924 | /* Increment the version number here. We can't let the caller | ||
1925 | set it beforehand, because we might have had to do GC on a node | ||
1926 | of this file - and we'd end up reusing version numbers. | ||
1927 | */ | ||
1928 | if (f) { | ||
1929 | raw_inode->version = f->highest_version + 1; | ||
1930 | D1(printk (KERN_NOTICE "jffs_write_node(): setting version of %s to %d\n", f->name, raw_inode->version)); | ||
1931 | |||
1932 | /* if the file was deleted, set the deleted bit in the raw inode */ | ||
1933 | if (f->deleted) | ||
1934 | raw_inode->deleted = 1; | ||
1935 | } | ||
1936 | |||
1937 | /* Compute the checksum for the data and name chunks. */ | ||
1938 | raw_inode->dchksum = jffs_checksum(data, raw_inode->dsize); | ||
1939 | raw_inode->nchksum = jffs_checksum(name, raw_inode->nsize); | ||
1940 | |||
1941 | /* The checksum is calculated without the chksum and accurate | ||
1942 | fields so set them to zero first. */ | ||
1943 | raw_inode->accurate = 0; | ||
1944 | raw_inode->chksum = 0; | ||
1945 | raw_inode->chksum = jffs_checksum(raw_inode, | ||
1946 | sizeof(struct jffs_raw_inode)); | ||
1947 | raw_inode->accurate = 0xff; | ||
1948 | |||
1949 | D3(printk("jffs_write_node(): About to write this raw inode to the " | ||
1950 | "flash at pos 0x%lx:\n", (long)pos)); | ||
1951 | D3(jffs_print_raw_inode(raw_inode)); | ||
1952 | |||
1953 | /* The actual raw JFFS node */ | ||
1954 | node_iovec[0].iov_base = (void *) raw_inode; | ||
1955 | node_iovec[0].iov_len = (size_t) sizeof(struct jffs_raw_inode); | ||
1956 | iovec_cnt = 1; | ||
1957 | |||
1958 | /* Get name and size if there is one */ | ||
1959 | if (raw_inode->nsize) { | ||
1960 | node_iovec[iovec_cnt].iov_base = (void *) name; | ||
1961 | node_iovec[iovec_cnt].iov_len = (size_t) raw_inode->nsize; | ||
1962 | iovec_cnt++; | ||
1963 | |||
1964 | if (JFFS_GET_PAD_BYTES(raw_inode->nsize)) { | ||
1965 | static unsigned char allff[3]={255,255,255}; | ||
1966 | /* Add some extra padding if necessary */ | ||
1967 | node_iovec[iovec_cnt].iov_base = allff; | ||
1968 | node_iovec[iovec_cnt].iov_len = | ||
1969 | JFFS_GET_PAD_BYTES(raw_inode->nsize); | ||
1970 | iovec_cnt++; | ||
1971 | } | ||
1972 | } | ||
1973 | |||
1974 | /* Get data and size if there is any */ | ||
1975 | if (raw_inode->dsize) { | ||
1976 | node_iovec[iovec_cnt].iov_base = (void *) data; | ||
1977 | node_iovec[iovec_cnt].iov_len = (size_t) raw_inode->dsize; | ||
1978 | iovec_cnt++; | ||
1979 | /* No need to pad this because we're not actually putting | ||
1980 | anything after it. | ||
1981 | */ | ||
1982 | } | ||
1983 | |||
1984 | if ((err = flash_safe_writev(fmc->mtd, node_iovec, iovec_cnt, | ||
1985 | pos)) < 0) { | ||
1986 | jffs_fmfree_partly(fmc, fm, 0); | ||
1987 | jffs_fm_write_unlock(fmc); | ||
1988 | printk(KERN_ERR "JFFS: jffs_write_node: Failed to write, " | ||
1989 | "requested %i, wrote %i\n", total_size, err); | ||
1990 | goto retry; | ||
1991 | } | ||
1992 | if (raw_inode->deleted) | ||
1993 | f->deleted = 1; | ||
1994 | |||
1995 | jffs_fm_write_unlock(fmc); | ||
1996 | D3(printk("jffs_write_node(): Leaving...\n")); | ||
1997 | return raw_inode->dsize; | ||
1998 | } /* jffs_write_node() */ | ||
1999 | |||
2000 | |||
2001 | /* Read data from the node and write it to the buffer. 'node_offset' | ||
2002 | is how much we have read from this particular node before and which | ||
2003 | shouldn't be read again. 'max_size' is how much space there is in | ||
2004 | the buffer. */ | ||
2005 | static int | ||
2006 | jffs_get_node_data(struct jffs_file *f, struct jffs_node *node, | ||
2007 | unsigned char *buf,__u32 node_offset, __u32 max_size) | ||
2008 | { | ||
2009 | struct jffs_fmcontrol *fmc = f->c->fmc; | ||
2010 | __u32 pos = node->fm->offset + node->fm_offset + node_offset; | ||
2011 | __u32 avail = node->data_size - node_offset; | ||
2012 | __u32 r; | ||
2013 | |||
2014 | D2(printk(" jffs_get_node_data(): file: \"%s\", ino: %u, " | ||
2015 | "version: %u, node_offset: %u\n", | ||
2016 | f->name, node->ino, node->version, node_offset)); | ||
2017 | |||
2018 | r = min(avail, max_size); | ||
2019 | D3(printk(KERN_NOTICE "jffs_get_node_data\n")); | ||
2020 | flash_safe_read(fmc->mtd, pos, buf, r); | ||
2021 | |||
2022 | D3(printk(" jffs_get_node_data(): Read %u byte%s.\n", | ||
2023 | r, (r == 1 ? "" : "s"))); | ||
2024 | |||
2025 | return r; | ||
2026 | } | ||
2027 | |||
2028 | |||
2029 | /* Read data from the file's nodes. Write the data to the buffer | ||
2030 | 'buf'. 'read_offset' tells how much data we should skip. */ | ||
2031 | int | ||
2032 | jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset, | ||
2033 | __u32 size) | ||
2034 | { | ||
2035 | struct jffs_node *node; | ||
2036 | __u32 read_data = 0; /* Total amount of read data. */ | ||
2037 | __u32 node_offset = 0; | ||
2038 | __u32 pos = 0; /* Number of bytes traversed. */ | ||
2039 | |||
2040 | D2(printk("jffs_read_data(): file = \"%s\", read_offset = %d, " | ||
2041 | "size = %u\n", | ||
2042 | (f->name ? f->name : ""), read_offset, size)); | ||
2043 | |||
2044 | if (read_offset >= f->size) { | ||
2045 | D(printk(" f->size: %d\n", f->size)); | ||
2046 | return 0; | ||
2047 | } | ||
2048 | |||
2049 | /* First find the node to read data from. */ | ||
2050 | node = f->range_head; | ||
2051 | while (pos <= read_offset) { | ||
2052 | node_offset = read_offset - pos; | ||
2053 | if (node_offset >= node->data_size) { | ||
2054 | pos += node->data_size; | ||
2055 | node = node->range_next; | ||
2056 | } | ||
2057 | else { | ||
2058 | break; | ||
2059 | } | ||
2060 | } | ||
2061 | |||
2062 | /* "Cats are living proof that not everything in nature | ||
2063 | has to be useful." | ||
2064 | - Garrison Keilor ('97) */ | ||
2065 | |||
2066 | /* Fill the buffer. */ | ||
2067 | while (node && (read_data < size)) { | ||
2068 | int r; | ||
2069 | if (!node->fm) { | ||
2070 | /* This node does not refer to real data. */ | ||
2071 | r = min(size - read_data, | ||
2072 | node->data_size - node_offset); | ||
2073 | memset(&buf[read_data], 0, r); | ||
2074 | } | ||
2075 | else if ((r = jffs_get_node_data(f, node, &buf[read_data], | ||
2076 | node_offset, | ||
2077 | size - read_data)) < 0) { | ||
2078 | return r; | ||
2079 | } | ||
2080 | read_data += r; | ||
2081 | node_offset = 0; | ||
2082 | node = node->range_next; | ||
2083 | } | ||
2084 | D3(printk(" jffs_read_data(): Read %u bytes.\n", read_data)); | ||
2085 | return read_data; | ||
2086 | } | ||
2087 | |||
2088 | |||
2089 | /* Used for traversing all nodes in the hash table. */ | ||
2090 | int | ||
2091 | jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *)) | ||
2092 | { | ||
2093 | int pos; | ||
2094 | int r; | ||
2095 | int result = 0; | ||
2096 | |||
2097 | for (pos = 0; pos < c->hash_len; pos++) { | ||
2098 | struct jffs_file *f, *next; | ||
2099 | |||
2100 | /* We must do _safe, because 'func' might remove the | ||
2101 | current file 'f' from the list. */ | ||
2102 | list_for_each_entry_safe(f, next, &c->hash[pos], hash) { | ||
2103 | r = func(f); | ||
2104 | if (r < 0) | ||
2105 | return r; | ||
2106 | result += r; | ||
2107 | } | ||
2108 | } | ||
2109 | |||
2110 | return result; | ||
2111 | } | ||
2112 | |||
2113 | |||
2114 | /* Free all nodes associated with a file. */ | ||
2115 | static int | ||
2116 | jffs_free_node_list(struct jffs_file *f) | ||
2117 | { | ||
2118 | struct jffs_node *node; | ||
2119 | struct jffs_node *p; | ||
2120 | |||
2121 | D3(printk("jffs_free_node_list(): f #%u, \"%s\"\n", | ||
2122 | f->ino, (f->name ? f->name : ""))); | ||
2123 | node = f->version_head; | ||
2124 | while (node) { | ||
2125 | p = node; | ||
2126 | node = node->version_next; | ||
2127 | jffs_free_node(p); | ||
2128 | DJM(no_jffs_node--); | ||
2129 | } | ||
2130 | return 0; | ||
2131 | } | ||
2132 | |||
2133 | |||
2134 | /* Free a file and its name. */ | ||
2135 | static int | ||
2136 | jffs_free_file(struct jffs_file *f) | ||
2137 | { | ||
2138 | D3(printk("jffs_free_file: f #%u, \"%s\"\n", | ||
2139 | f->ino, (f->name ? f->name : ""))); | ||
2140 | |||
2141 | if (f->name) { | ||
2142 | kfree(f->name); | ||
2143 | DJM(no_name--); | ||
2144 | } | ||
2145 | kfree(f); | ||
2146 | no_jffs_file--; | ||
2147 | return 0; | ||
2148 | } | ||
2149 | |||
2150 | static long | ||
2151 | jffs_get_file_count(void) | ||
2152 | { | ||
2153 | return no_jffs_file; | ||
2154 | } | ||
2155 | |||
2156 | /* See if a file is deleted. If so, mark that file's nodes as obsolete. */ | ||
2157 | int | ||
2158 | jffs_possibly_delete_file(struct jffs_file *f) | ||
2159 | { | ||
2160 | struct jffs_node *n; | ||
2161 | |||
2162 | D3(printk("jffs_possibly_delete_file(): ino: %u\n", | ||
2163 | f->ino)); | ||
2164 | |||
2165 | ASSERT(if (!f) { | ||
2166 | printk(KERN_ERR "jffs_possibly_delete_file(): f == NULL\n"); | ||
2167 | return -1; | ||
2168 | }); | ||
2169 | |||
2170 | if (f->deleted) { | ||
2171 | /* First try to remove all older versions. Commence with | ||
2172 | the oldest node. */ | ||
2173 | for (n = f->version_head; n; n = n->version_next) { | ||
2174 | if (!n->fm) { | ||
2175 | continue; | ||
2176 | } | ||
2177 | if (jffs_fmfree(f->c->fmc, n->fm, n) < 0) { | ||
2178 | break; | ||
2179 | } | ||
2180 | } | ||
2181 | /* Unlink the file from the filesystem. */ | ||
2182 | if (!f->c->building_fs) { | ||
2183 | jffs_unlink_file_from_tree(f); | ||
2184 | } | ||
2185 | jffs_unlink_file_from_hash(f); | ||
2186 | jffs_free_node_list(f); | ||
2187 | jffs_free_file(f); | ||
2188 | } | ||
2189 | return 0; | ||
2190 | } | ||
2191 | |||
2192 | |||
2193 | /* Used in conjunction with jffs_foreach_file() to count the number | ||
2194 | of files in the file system. */ | ||
2195 | int | ||
2196 | jffs_file_count(struct jffs_file *f) | ||
2197 | { | ||
2198 | return 1; | ||
2199 | } | ||
2200 | |||
2201 | |||
2202 | /* Build up a file's range list from scratch by going through the | ||
2203 | version list. */ | ||
2204 | static int | ||
2205 | jffs_build_file(struct jffs_file *f) | ||
2206 | { | ||
2207 | struct jffs_node *n; | ||
2208 | |||
2209 | D3(printk("jffs_build_file(): ino: %u, name: \"%s\"\n", | ||
2210 | f->ino, (f->name ? f->name : ""))); | ||
2211 | |||
2212 | for (n = f->version_head; n; n = n->version_next) { | ||
2213 | jffs_update_file(f, n); | ||
2214 | } | ||
2215 | return 0; | ||
2216 | } | ||
2217 | |||
2218 | |||
2219 | /* Remove an amount of data from a file. If this amount of data is | ||
2220 | zero, that could mean that a node should be split in two parts. | ||
2221 | We remove or change the appropriate nodes in the lists. | ||
2222 | |||
2223 | Starting offset of area to be removed is node->data_offset, | ||
2224 | and the length of the area is in node->removed_size. */ | ||
2225 | static int | ||
2226 | jffs_delete_data(struct jffs_file *f, struct jffs_node *node) | ||
2227 | { | ||
2228 | struct jffs_node *n; | ||
2229 | __u32 offset = node->data_offset; | ||
2230 | __u32 remove_size = node->removed_size; | ||
2231 | |||
2232 | D3(printk("jffs_delete_data(): offset = %u, remove_size = %u\n", | ||
2233 | offset, remove_size)); | ||
2234 | |||
2235 | if (remove_size == 0 | ||
2236 | && f->range_tail | ||
2237 | && f->range_tail->data_offset + f->range_tail->data_size | ||
2238 | == offset) { | ||
2239 | /* A simple append; nothing to remove or no node to split. */ | ||
2240 | return 0; | ||
2241 | } | ||
2242 | |||
2243 | /* Find the node where we should begin the removal. */ | ||
2244 | for (n = f->range_head; n; n = n->range_next) { | ||
2245 | if (n->data_offset + n->data_size > offset) { | ||
2246 | break; | ||
2247 | } | ||
2248 | } | ||
2249 | if (!n) { | ||
2250 | /* If there's no data in the file there's no data to | ||
2251 | remove either. */ | ||
2252 | return 0; | ||
2253 | } | ||
2254 | |||
2255 | if (n->data_offset > offset) { | ||
2256 | /* XXX: Not implemented yet. */ | ||
2257 | printk(KERN_WARNING "JFFS: An unexpected situation " | ||
2258 | "occurred in jffs_delete_data.\n"); | ||
2259 | } | ||
2260 | else if (n->data_offset < offset) { | ||
2261 | /* See if the node has to be split into two parts. */ | ||
2262 | if (n->data_offset + n->data_size > offset + remove_size) { | ||
2263 | /* Do the split. */ | ||
2264 | struct jffs_node *new_node; | ||
2265 | D3(printk("jffs_delete_data(): Split node with " | ||
2266 | "version number %u.\n", n->version)); | ||
2267 | |||
2268 | if (!(new_node = jffs_alloc_node())) { | ||
2269 | D(printk("jffs_delete_data(): -ENOMEM\n")); | ||
2270 | return -ENOMEM; | ||
2271 | } | ||
2272 | DJM(no_jffs_node++); | ||
2273 | |||
2274 | new_node->ino = n->ino; | ||
2275 | new_node->version = n->version; | ||
2276 | new_node->data_offset = offset; | ||
2277 | new_node->data_size = n->data_size - (remove_size + (offset - n->data_offset)); | ||
2278 | new_node->fm_offset = n->fm_offset + (remove_size + (offset - n->data_offset)); | ||
2279 | new_node->name_size = n->name_size; | ||
2280 | new_node->fm = n->fm; | ||
2281 | new_node->version_prev = n; | ||
2282 | new_node->version_next = n->version_next; | ||
2283 | if (new_node->version_next) { | ||
2284 | new_node->version_next->version_prev | ||
2285 | = new_node; | ||
2286 | } | ||
2287 | else { | ||
2288 | f->version_tail = new_node; | ||
2289 | } | ||
2290 | n->version_next = new_node; | ||
2291 | new_node->range_prev = n; | ||
2292 | new_node->range_next = n->range_next; | ||
2293 | if (new_node->range_next) { | ||
2294 | new_node->range_next->range_prev = new_node; | ||
2295 | } | ||
2296 | else { | ||
2297 | f->range_tail = new_node; | ||
2298 | } | ||
2299 | /* A very interesting can of worms. */ | ||
2300 | n->range_next = new_node; | ||
2301 | n->data_size = offset - n->data_offset; | ||
2302 | if (new_node->fm) | ||
2303 | jffs_add_node(new_node); | ||
2304 | else { | ||
2305 | D1(printk(KERN_WARNING "jffs_delete_data(): Splitting an empty node (file hold).\n!")); | ||
2306 | D1(printk(KERN_WARNING "FIXME: Did dwmw2 do the right thing here?\n")); | ||
2307 | } | ||
2308 | n = new_node->range_next; | ||
2309 | remove_size = 0; | ||
2310 | } | ||
2311 | else { | ||
2312 | /* No. No need to split the node. Just remove | ||
2313 | the end of the node. */ | ||
2314 | int r = min(n->data_offset + n->data_size | ||
2315 | - offset, remove_size); | ||
2316 | n->data_size -= r; | ||
2317 | remove_size -= r; | ||
2318 | n = n->range_next; | ||
2319 | } | ||
2320 | } | ||
2321 | |||
2322 | /* Remove as many nodes as necessary. */ | ||
2323 | while (n && remove_size) { | ||
2324 | if (n->data_size <= remove_size) { | ||
2325 | struct jffs_node *p = n; | ||
2326 | remove_size -= n->data_size; | ||
2327 | n = n->range_next; | ||
2328 | D3(printk("jffs_delete_data(): Removing node: " | ||
2329 | "ino: %u, version: %u%s\n", | ||
2330 | p->ino, p->version, | ||
2331 | (p->fm ? "" : " (virtual)"))); | ||
2332 | if (p->fm) { | ||
2333 | jffs_fmfree(f->c->fmc, p->fm, p); | ||
2334 | } | ||
2335 | jffs_unlink_node_from_range_list(f, p); | ||
2336 | jffs_unlink_node_from_version_list(f, p); | ||
2337 | jffs_free_node(p); | ||
2338 | DJM(no_jffs_node--); | ||
2339 | } | ||
2340 | else { | ||
2341 | n->data_size -= remove_size; | ||
2342 | n->fm_offset += remove_size; | ||
2343 | n->data_offset -= (node->removed_size - remove_size); | ||
2344 | n = n->range_next; | ||
2345 | break; | ||
2346 | } | ||
2347 | } | ||
2348 | |||
2349 | /* Adjust the following nodes' information about offsets etc. */ | ||
2350 | while (n && node->removed_size) { | ||
2351 | n->data_offset -= node->removed_size; | ||
2352 | n = n->range_next; | ||
2353 | } | ||
2354 | |||
2355 | if (node->removed_size > (f->size - node->data_offset)) { | ||
2356 | /* It's possible that the removed_size is in fact | ||
2357 | * greater than the amount of data we actually thought | ||
2358 | * were present in the first place - some of the nodes | ||
2359 | * which this node originally obsoleted may already have | ||
2360 | * been deleted from the flash by subsequent garbage | ||
2361 | * collection. | ||
2362 | * | ||
2363 | * If this is the case, don't let f->size go negative. | ||
2364 | * Bad things would happen :) | ||
2365 | */ | ||
2366 | f->size = node->data_offset; | ||
2367 | } else { | ||
2368 | f->size -= node->removed_size; | ||
2369 | } | ||
2370 | D3(printk("jffs_delete_data(): f->size = %d\n", f->size)); | ||
2371 | return 0; | ||
2372 | } /* jffs_delete_data() */ | ||
2373 | |||
2374 | |||
2375 | /* Insert some data into a file. Prior to the call to this function, | ||
2376 | jffs_delete_data should be called. */ | ||
2377 | static int | ||
2378 | jffs_insert_data(struct jffs_file *f, struct jffs_node *node) | ||
2379 | { | ||
2380 | D3(printk("jffs_insert_data(): node->data_offset = %u, " | ||
2381 | "node->data_size = %u, f->size = %u\n", | ||
2382 | node->data_offset, node->data_size, f->size)); | ||
2383 | |||
2384 | /* Find the position where we should insert data. */ | ||
2385 | retry: | ||
2386 | if (node->data_offset == f->size) { | ||
2387 | /* A simple append. This is the most common operation. */ | ||
2388 | node->range_next = NULL; | ||
2389 | node->range_prev = f->range_tail; | ||
2390 | if (node->range_prev) { | ||
2391 | node->range_prev->range_next = node; | ||
2392 | } | ||
2393 | f->range_tail = node; | ||
2394 | f->size += node->data_size; | ||
2395 | if (!f->range_head) { | ||
2396 | f->range_head = node; | ||
2397 | } | ||
2398 | } | ||
2399 | else if (node->data_offset < f->size) { | ||
2400 | /* Trying to insert data into the middle of the file. This | ||
2401 | means no problem because jffs_delete_data() has already | ||
2402 | prepared the range list for us. */ | ||
2403 | struct jffs_node *n; | ||
2404 | |||
2405 | /* Find the correct place for the insertion and then insert | ||
2406 | the node. */ | ||
2407 | for (n = f->range_head; n; n = n->range_next) { | ||
2408 | D2(printk("Cool stuff's happening!\n")); | ||
2409 | |||
2410 | if (n->data_offset == node->data_offset) { | ||
2411 | node->range_prev = n->range_prev; | ||
2412 | if (node->range_prev) { | ||
2413 | node->range_prev->range_next = node; | ||
2414 | } | ||
2415 | else { | ||
2416 | f->range_head = node; | ||
2417 | } | ||
2418 | node->range_next = n; | ||
2419 | n->range_prev = node; | ||
2420 | break; | ||
2421 | } | ||
2422 | ASSERT(else if (n->data_offset + n->data_size > | ||
2423 | node->data_offset) { | ||
2424 | printk(KERN_ERR "jffs_insert_data(): " | ||
2425 | "Couldn't find a place to insert " | ||
2426 | "the data!\n"); | ||
2427 | return -1; | ||
2428 | }); | ||
2429 | } | ||
2430 | |||
2431 | /* Adjust later nodes' offsets etc. */ | ||
2432 | n = node->range_next; | ||
2433 | while (n) { | ||
2434 | n->data_offset += node->data_size; | ||
2435 | n = n->range_next; | ||
2436 | } | ||
2437 | f->size += node->data_size; | ||
2438 | } | ||
2439 | else if (node->data_offset > f->size) { | ||
2440 | /* Okay. This is tricky. This means that we want to insert | ||
2441 | data at a place that is beyond the limits of the file as | ||
2442 | it is constructed right now. This is actually a common | ||
2443 | event that for instance could occur during the mounting | ||
2444 | of the file system if a large file have been truncated, | ||
2445 | rewritten and then only partially garbage collected. */ | ||
2446 | |||
2447 | struct jffs_node *n; | ||
2448 | |||
2449 | /* We need a place holder for the data that is missing in | ||
2450 | front of this insertion. This "virtual node" will not | ||
2451 | be associated with any space on the flash device. */ | ||
2452 | struct jffs_node *virtual_node; | ||
2453 | if (!(virtual_node = jffs_alloc_node())) { | ||
2454 | return -ENOMEM; | ||
2455 | } | ||
2456 | |||
2457 | D(printk("jffs_insert_data: Inserting a virtual node.\n")); | ||
2458 | D(printk(" node->data_offset = %u\n", node->data_offset)); | ||
2459 | D(printk(" f->size = %u\n", f->size)); | ||
2460 | |||
2461 | virtual_node->ino = node->ino; | ||
2462 | virtual_node->version = node->version; | ||
2463 | virtual_node->removed_size = 0; | ||
2464 | virtual_node->fm_offset = 0; | ||
2465 | virtual_node->name_size = 0; | ||
2466 | virtual_node->fm = NULL; /* This is a virtual data holder. */ | ||
2467 | virtual_node->version_prev = NULL; | ||
2468 | virtual_node->version_next = NULL; | ||
2469 | virtual_node->range_next = NULL; | ||
2470 | |||
2471 | /* Are there any data at all in the file yet? */ | ||
2472 | if (f->range_head) { | ||
2473 | virtual_node->data_offset | ||
2474 | = f->range_tail->data_offset | ||
2475 | + f->range_tail->data_size; | ||
2476 | virtual_node->data_size | ||
2477 | = node->data_offset - virtual_node->data_offset; | ||
2478 | virtual_node->range_prev = f->range_tail; | ||
2479 | f->range_tail->range_next = virtual_node; | ||
2480 | } | ||
2481 | else { | ||
2482 | virtual_node->data_offset = 0; | ||
2483 | virtual_node->data_size = node->data_offset; | ||
2484 | virtual_node->range_prev = NULL; | ||
2485 | f->range_head = virtual_node; | ||
2486 | } | ||
2487 | |||
2488 | f->range_tail = virtual_node; | ||
2489 | f->size += virtual_node->data_size; | ||
2490 | |||
2491 | /* Insert this virtual node in the version list as well. */ | ||
2492 | for (n = f->version_head; n ; n = n->version_next) { | ||
2493 | if (n->version == virtual_node->version) { | ||
2494 | virtual_node->version_prev = n->version_prev; | ||
2495 | n->version_prev = virtual_node; | ||
2496 | if (virtual_node->version_prev) { | ||
2497 | virtual_node->version_prev | ||
2498 | ->version_next = virtual_node; | ||
2499 | } | ||
2500 | else { | ||
2501 | f->version_head = virtual_node; | ||
2502 | } | ||
2503 | virtual_node->version_next = n; | ||
2504 | break; | ||
2505 | } | ||
2506 | } | ||
2507 | |||
2508 | D(jffs_print_node(virtual_node)); | ||
2509 | |||
2510 | /* Make a new try to insert the node. */ | ||
2511 | goto retry; | ||
2512 | } | ||
2513 | |||
2514 | D3(printk("jffs_insert_data(): f->size = %d\n", f->size)); | ||
2515 | return 0; | ||
2516 | } | ||
2517 | |||
2518 | |||
2519 | /* A new node (with data) has been added to the file and now the range | ||
2520 | list has to be modified. */ | ||
2521 | static int | ||
2522 | jffs_update_file(struct jffs_file *f, struct jffs_node *node) | ||
2523 | { | ||
2524 | int err; | ||
2525 | |||
2526 | D3(printk("jffs_update_file(): ino: %u, version: %u\n", | ||
2527 | f->ino, node->version)); | ||
2528 | |||
2529 | if (node->data_size == 0) { | ||
2530 | if (node->removed_size == 0) { | ||
2531 | /* data_offset == X */ | ||
2532 | /* data_size == 0 */ | ||
2533 | /* remove_size == 0 */ | ||
2534 | } | ||
2535 | else { | ||
2536 | /* data_offset == X */ | ||
2537 | /* data_size == 0 */ | ||
2538 | /* remove_size != 0 */ | ||
2539 | if ((err = jffs_delete_data(f, node)) < 0) { | ||
2540 | return err; | ||
2541 | } | ||
2542 | } | ||
2543 | } | ||
2544 | else { | ||
2545 | /* data_offset == X */ | ||
2546 | /* data_size != 0 */ | ||
2547 | /* remove_size == Y */ | ||
2548 | if ((err = jffs_delete_data(f, node)) < 0) { | ||
2549 | return err; | ||
2550 | } | ||
2551 | if ((err = jffs_insert_data(f, node)) < 0) { | ||
2552 | return err; | ||
2553 | } | ||
2554 | } | ||
2555 | return 0; | ||
2556 | } | ||
2557 | |||
2558 | /* Print the contents of a file. */ | ||
2559 | #if 0 | ||
2560 | int | ||
2561 | jffs_print_file(struct jffs_file *f) | ||
2562 | { | ||
2563 | D(int i); | ||
2564 | D(printk("jffs_file: 0x%p\n", f)); | ||
2565 | D(printk("{\n")); | ||
2566 | D(printk(" 0x%08x, /* ino */\n", f->ino)); | ||
2567 | D(printk(" 0x%08x, /* pino */\n", f->pino)); | ||
2568 | D(printk(" 0x%08x, /* mode */\n", f->mode)); | ||
2569 | D(printk(" 0x%04x, /* uid */\n", f->uid)); | ||
2570 | D(printk(" 0x%04x, /* gid */\n", f->gid)); | ||
2571 | D(printk(" 0x%08x, /* atime */\n", f->atime)); | ||
2572 | D(printk(" 0x%08x, /* mtime */\n", f->mtime)); | ||
2573 | D(printk(" 0x%08x, /* ctime */\n", f->ctime)); | ||
2574 | D(printk(" 0x%02x, /* nsize */\n", f->nsize)); | ||
2575 | D(printk(" 0x%02x, /* nlink */\n", f->nlink)); | ||
2576 | D(printk(" 0x%02x, /* deleted */\n", f->deleted)); | ||
2577 | D(printk(" \"%s\", ", (f->name ? f->name : ""))); | ||
2578 | D(for (i = strlen(f->name ? f->name : ""); i < 8; ++i) { | ||
2579 | printk(" "); | ||
2580 | }); | ||
2581 | D(printk("/* name */\n")); | ||
2582 | D(printk(" 0x%08x, /* size */\n", f->size)); | ||
2583 | D(printk(" 0x%08x, /* highest_version */\n", | ||
2584 | f->highest_version)); | ||
2585 | D(printk(" 0x%p, /* c */\n", f->c)); | ||
2586 | D(printk(" 0x%p, /* parent */\n", f->parent)); | ||
2587 | D(printk(" 0x%p, /* children */\n", f->children)); | ||
2588 | D(printk(" 0x%p, /* sibling_prev */\n", f->sibling_prev)); | ||
2589 | D(printk(" 0x%p, /* sibling_next */\n", f->sibling_next)); | ||
2590 | D(printk(" 0x%p, /* hash_prev */\n", f->hash.prev)); | ||
2591 | D(printk(" 0x%p, /* hash_next */\n", f->hash.next)); | ||
2592 | D(printk(" 0x%p, /* range_head */\n", f->range_head)); | ||
2593 | D(printk(" 0x%p, /* range_tail */\n", f->range_tail)); | ||
2594 | D(printk(" 0x%p, /* version_head */\n", f->version_head)); | ||
2595 | D(printk(" 0x%p, /* version_tail */\n", f->version_tail)); | ||
2596 | D(printk("}\n")); | ||
2597 | return 0; | ||
2598 | } | ||
2599 | #endif /* 0 */ | ||
2600 | |||
2601 | void | ||
2602 | jffs_print_hash_table(struct jffs_control *c) | ||
2603 | { | ||
2604 | int i; | ||
2605 | |||
2606 | printk("JFFS: Dumping the file system's hash table...\n"); | ||
2607 | for (i = 0; i < c->hash_len; i++) { | ||
2608 | struct jffs_file *f; | ||
2609 | list_for_each_entry(f, &c->hash[i], hash) { | ||
2610 | printk("*** c->hash[%u]: \"%s\" " | ||
2611 | "(ino: %u, pino: %u)\n", | ||
2612 | i, (f->name ? f->name : ""), | ||
2613 | f->ino, f->pino); | ||
2614 | } | ||
2615 | } | ||
2616 | } | ||
2617 | |||
2618 | |||
2619 | void | ||
2620 | jffs_print_tree(struct jffs_file *first_file, int indent) | ||
2621 | { | ||
2622 | struct jffs_file *f; | ||
2623 | char *space; | ||
2624 | int dir; | ||
2625 | |||
2626 | if (!first_file) { | ||
2627 | return; | ||
2628 | } | ||
2629 | |||
2630 | if (!(space = kmalloc(indent + 1, GFP_KERNEL))) { | ||
2631 | printk("jffs_print_tree(): Out of memory!\n"); | ||
2632 | return; | ||
2633 | } | ||
2634 | |||
2635 | memset(space, ' ', indent); | ||
2636 | space[indent] = '\0'; | ||
2637 | |||
2638 | for (f = first_file; f; f = f->sibling_next) { | ||
2639 | dir = S_ISDIR(f->mode); | ||
2640 | printk("%s%s%s (ino: %u, highest_version: %u, size: %u)\n", | ||
2641 | space, (f->name ? f->name : ""), (dir ? "/" : ""), | ||
2642 | f->ino, f->highest_version, f->size); | ||
2643 | if (dir) { | ||
2644 | jffs_print_tree(f->children, indent + 2); | ||
2645 | } | ||
2646 | } | ||
2647 | |||
2648 | kfree(space); | ||
2649 | } | ||
2650 | |||
2651 | |||
2652 | #if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG | ||
2653 | void | ||
2654 | jffs_print_memory_allocation_statistics(void) | ||
2655 | { | ||
2656 | static long printout; | ||
2657 | printk("________ Memory printout #%ld ________\n", ++printout); | ||
2658 | printk("no_jffs_file = %ld\n", no_jffs_file); | ||
2659 | printk("no_jffs_node = %ld\n", no_jffs_node); | ||
2660 | printk("no_jffs_control = %ld\n", no_jffs_control); | ||
2661 | printk("no_jffs_raw_inode = %ld\n", no_jffs_raw_inode); | ||
2662 | printk("no_jffs_node_ref = %ld\n", no_jffs_node_ref); | ||
2663 | printk("no_jffs_fm = %ld\n", no_jffs_fm); | ||
2664 | printk("no_jffs_fmcontrol = %ld\n", no_jffs_fmcontrol); | ||
2665 | printk("no_hash = %ld\n", no_hash); | ||
2666 | printk("no_name = %ld\n", no_name); | ||
2667 | printk("\n"); | ||
2668 | } | ||
2669 | #endif | ||
2670 | |||
2671 | |||
2672 | /* Rewrite `size' bytes, and begin at `node'. */ | ||
2673 | static int | ||
2674 | jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, __u32 size) | ||
2675 | { | ||
2676 | struct jffs_control *c = f->c; | ||
2677 | struct jffs_fmcontrol *fmc = c->fmc; | ||
2678 | struct jffs_raw_inode raw_inode; | ||
2679 | struct jffs_node *new_node; | ||
2680 | struct jffs_fm *fm; | ||
2681 | __u32 pos; | ||
2682 | __u32 pos_dchksum; | ||
2683 | __u32 total_name_size; | ||
2684 | __u32 total_data_size; | ||
2685 | __u32 total_size; | ||
2686 | int err; | ||
2687 | |||
2688 | D1(printk("***jffs_rewrite_data(): node: %u, name: \"%s\", size: %u\n", | ||
2689 | f->ino, (f->name ? f->name : "(null)"), size)); | ||
2690 | |||
2691 | /* Create and initialize the new node. */ | ||
2692 | if (!(new_node = jffs_alloc_node())) { | ||
2693 | D(printk("jffs_rewrite_data(): " | ||
2694 | "Failed to allocate node.\n")); | ||
2695 | return -ENOMEM; | ||
2696 | } | ||
2697 | DJM(no_jffs_node++); | ||
2698 | new_node->data_offset = node->data_offset; | ||
2699 | new_node->removed_size = size; | ||
2700 | total_name_size = JFFS_PAD(f->nsize); | ||
2701 | total_data_size = JFFS_PAD(size); | ||
2702 | total_size = sizeof(struct jffs_raw_inode) | ||
2703 | + total_name_size + total_data_size; | ||
2704 | new_node->fm_offset = sizeof(struct jffs_raw_inode) | ||
2705 | + total_name_size; | ||
2706 | |||
2707 | retry: | ||
2708 | jffs_fm_write_lock(fmc); | ||
2709 | err = 0; | ||
2710 | |||
2711 | if ((err = jffs_fmalloc(fmc, total_size, new_node, &fm)) < 0) { | ||
2712 | DJM(no_jffs_node--); | ||
2713 | jffs_fm_write_unlock(fmc); | ||
2714 | D(printk("jffs_rewrite_data(): Failed to allocate fm.\n")); | ||
2715 | jffs_free_node(new_node); | ||
2716 | return err; | ||
2717 | } | ||
2718 | else if (!fm->nodes) { | ||
2719 | /* The jffs_fm struct that we got is not big enough. */ | ||
2720 | /* This should never happen, because we deal with this case | ||
2721 | in jffs_garbage_collect_next().*/ | ||
2722 | printk(KERN_WARNING "jffs_rewrite_data(): Allocated node is too small (%d bytes of %d)\n", fm->size, total_size); | ||
2723 | if ((err = jffs_write_dummy_node(c, fm)) < 0) { | ||
2724 | D(printk("jffs_rewrite_data(): " | ||
2725 | "jffs_write_dummy_node() Failed!\n")); | ||
2726 | } else { | ||
2727 | err = -ENOSPC; | ||
2728 | } | ||
2729 | DJM(no_jffs_fm--); | ||
2730 | jffs_fm_write_unlock(fmc); | ||
2731 | kfree(fm); | ||
2732 | |||
2733 | return err; | ||
2734 | } | ||
2735 | new_node->fm = fm; | ||
2736 | |||
2737 | /* Initialize the raw inode. */ | ||
2738 | raw_inode.magic = JFFS_MAGIC_BITMASK; | ||
2739 | raw_inode.ino = f->ino; | ||
2740 | raw_inode.pino = f->pino; | ||
2741 | raw_inode.version = f->highest_version + 1; | ||
2742 | raw_inode.mode = f->mode; | ||
2743 | raw_inode.uid = f->uid; | ||
2744 | raw_inode.gid = f->gid; | ||
2745 | raw_inode.atime = f->atime; | ||
2746 | raw_inode.mtime = f->mtime; | ||
2747 | raw_inode.ctime = f->ctime; | ||
2748 | raw_inode.offset = node->data_offset; | ||
2749 | raw_inode.dsize = size; | ||
2750 | raw_inode.rsize = size; | ||
2751 | raw_inode.nsize = f->nsize; | ||
2752 | raw_inode.nlink = f->nlink; | ||
2753 | raw_inode.spare = 0; | ||
2754 | raw_inode.rename = 0; | ||
2755 | raw_inode.deleted = f->deleted; | ||
2756 | raw_inode.accurate = 0xff; | ||
2757 | raw_inode.dchksum = 0; | ||
2758 | raw_inode.nchksum = 0; | ||
2759 | |||
2760 | pos = new_node->fm->offset; | ||
2761 | pos_dchksum = pos +JFFS_RAW_INODE_DCHKSUM_OFFSET; | ||
2762 | |||
2763 | D3(printk("jffs_rewrite_data(): Writing this raw inode " | ||
2764 | "to pos 0x%ul.\n", pos)); | ||
2765 | D3(jffs_print_raw_inode(&raw_inode)); | ||
2766 | |||
2767 | if ((err = flash_safe_write(fmc->mtd, pos, | ||
2768 | (u_char *) &raw_inode, | ||
2769 | sizeof(struct jffs_raw_inode) | ||
2770 | - sizeof(__u32) | ||
2771 | - sizeof(__u16) - sizeof(__u16))) < 0) { | ||
2772 | jffs_fmfree_partly(fmc, fm, | ||
2773 | total_name_size + total_data_size); | ||
2774 | jffs_fm_write_unlock(fmc); | ||
2775 | printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during " | ||
2776 | "rewrite. (raw inode)\n"); | ||
2777 | printk(KERN_ERR "JFFS: jffs_rewrite_data: Now retrying " | ||
2778 | "rewrite. (raw inode)\n"); | ||
2779 | goto retry; | ||
2780 | } | ||
2781 | pos += sizeof(struct jffs_raw_inode); | ||
2782 | |||
2783 | /* Write the name to the flash memory. */ | ||
2784 | if (f->nsize) { | ||
2785 | D3(printk("jffs_rewrite_data(): Writing name \"%s\" to " | ||
2786 | "pos 0x%ul.\n", f->name, (unsigned int) pos)); | ||
2787 | if ((err = flash_safe_write(fmc->mtd, pos, | ||
2788 | (u_char *)f->name, | ||
2789 | f->nsize)) < 0) { | ||
2790 | jffs_fmfree_partly(fmc, fm, total_data_size); | ||
2791 | jffs_fm_write_unlock(fmc); | ||
2792 | printk(KERN_ERR "JFFS: jffs_rewrite_data: Write " | ||
2793 | "error during rewrite. (name)\n"); | ||
2794 | printk(KERN_ERR "JFFS: jffs_rewrite_data: Now retrying " | ||
2795 | "rewrite. (name)\n"); | ||
2796 | goto retry; | ||
2797 | } | ||
2798 | pos += total_name_size; | ||
2799 | raw_inode.nchksum = jffs_checksum(f->name, f->nsize); | ||
2800 | } | ||
2801 | |||
2802 | /* Write the data. */ | ||
2803 | if (size) { | ||
2804 | int r; | ||
2805 | unsigned char *page; | ||
2806 | __u32 offset = node->data_offset; | ||
2807 | |||
2808 | if (!(page = (unsigned char *)__get_free_page(GFP_KERNEL))) { | ||
2809 | jffs_fmfree_partly(fmc, fm, 0); | ||
2810 | return -1; | ||
2811 | } | ||
2812 | |||
2813 | while (size) { | ||
2814 | __u32 s = min(size, (__u32)PAGE_SIZE); | ||
2815 | if ((r = jffs_read_data(f, (char *)page, | ||
2816 | offset, s)) < s) { | ||
2817 | free_page((unsigned long)page); | ||
2818 | jffs_fmfree_partly(fmc, fm, 0); | ||
2819 | jffs_fm_write_unlock(fmc); | ||
2820 | printk(KERN_ERR "JFFS: jffs_rewrite_data: " | ||
2821 | "jffs_read_data() " | ||
2822 | "failed! (r = %d)\n", r); | ||
2823 | return -1; | ||
2824 | } | ||
2825 | if ((err = flash_safe_write(fmc->mtd, | ||
2826 | pos, page, r)) < 0) { | ||
2827 | free_page((unsigned long)page); | ||
2828 | jffs_fmfree_partly(fmc, fm, 0); | ||
2829 | jffs_fm_write_unlock(fmc); | ||
2830 | printk(KERN_ERR "JFFS: jffs_rewrite_data: " | ||
2831 | "Write error during rewrite. " | ||
2832 | "(data)\n"); | ||
2833 | goto retry; | ||
2834 | } | ||
2835 | pos += r; | ||
2836 | size -= r; | ||
2837 | offset += r; | ||
2838 | raw_inode.dchksum += jffs_checksum(page, r); | ||
2839 | } | ||
2840 | |||
2841 | free_page((unsigned long)page); | ||
2842 | } | ||
2843 | |||
2844 | raw_inode.accurate = 0; | ||
2845 | raw_inode.chksum = jffs_checksum(&raw_inode, | ||
2846 | sizeof(struct jffs_raw_inode) | ||
2847 | - sizeof(__u16)); | ||
2848 | |||
2849 | /* Add the checksum. */ | ||
2850 | if ((err | ||
2851 | = flash_safe_write(fmc->mtd, pos_dchksum, | ||
2852 | &((u_char *) | ||
2853 | &raw_inode)[JFFS_RAW_INODE_DCHKSUM_OFFSET], | ||
2854 | sizeof(__u32) + sizeof(__u16) | ||
2855 | + sizeof(__u16))) < 0) { | ||
2856 | jffs_fmfree_partly(fmc, fm, 0); | ||
2857 | jffs_fm_write_unlock(fmc); | ||
2858 | printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during " | ||
2859 | "rewrite. (checksum)\n"); | ||
2860 | goto retry; | ||
2861 | } | ||
2862 | |||
2863 | /* Now make the file system aware of the newly written node. */ | ||
2864 | jffs_insert_node(c, f, &raw_inode, f->name, new_node); | ||
2865 | jffs_fm_write_unlock(fmc); | ||
2866 | |||
2867 | D3(printk("jffs_rewrite_data(): Leaving...\n")); | ||
2868 | return 0; | ||
2869 | } /* jffs_rewrite_data() */ | ||
2870 | |||
2871 | |||
2872 | /* jffs_garbage_collect_next implements one step in the garbage collect | ||
2873 | process and is often called multiple times at each occasion of a | ||
2874 | garbage collect. */ | ||
2875 | |||
2876 | static int | ||
2877 | jffs_garbage_collect_next(struct jffs_control *c) | ||
2878 | { | ||
2879 | struct jffs_fmcontrol *fmc = c->fmc; | ||
2880 | struct jffs_node *node; | ||
2881 | struct jffs_file *f; | ||
2882 | int err = 0; | ||
2883 | __u32 size; | ||
2884 | __u32 data_size; | ||
2885 | __u32 total_name_size; | ||
2886 | __u32 extra_available; | ||
2887 | __u32 space_needed; | ||
2888 | __u32 free_chunk_size1 = jffs_free_size1(fmc); | ||
2889 | D2(__u32 free_chunk_size2 = jffs_free_size2(fmc)); | ||
2890 | |||
2891 | /* Get the oldest node in the flash. */ | ||
2892 | node = jffs_get_oldest_node(fmc); | ||
2893 | ASSERT(if (!node) { | ||
2894 | printk(KERN_ERR "JFFS: jffs_garbage_collect_next: " | ||
2895 | "No oldest node found!\n"); | ||
2896 | err = -1; | ||
2897 | goto jffs_garbage_collect_next_end; | ||
2898 | |||
2899 | |||
2900 | }); | ||
2901 | |||
2902 | /* Find its corresponding file too. */ | ||
2903 | f = jffs_find_file(c, node->ino); | ||
2904 | |||
2905 | if (!f) { | ||
2906 | printk (KERN_ERR "JFFS: jffs_garbage_collect_next: " | ||
2907 | "No file to garbage collect! " | ||
2908 | "(ino = 0x%08x)\n", node->ino); | ||
2909 | /* FIXME: Free the offending node and recover. */ | ||
2910 | err = -1; | ||
2911 | goto jffs_garbage_collect_next_end; | ||
2912 | } | ||
2913 | |||
2914 | /* We always write out the name. Theoretically, we don't need | ||
2915 | to, but for now it's easier - because otherwise we'd have | ||
2916 | to keep track of how many times the current name exists on | ||
2917 | the flash and make sure it never reaches zero. | ||
2918 | |||
2919 | The current approach means that would be possible to cause | ||
2920 | the GC to end up eating its tail by writing lots of nodes | ||
2921 | with no name for it to garbage-collect. Hence the change in | ||
2922 | inode.c to write names with _every_ node. | ||
2923 | |||
2924 | It sucks, but it _should_ work. | ||
2925 | */ | ||
2926 | total_name_size = JFFS_PAD(f->nsize); | ||
2927 | |||
2928 | D1(printk("jffs_garbage_collect_next(): \"%s\", " | ||
2929 | "ino: %u, version: %u, location 0x%x, dsize %u\n", | ||
2930 | (f->name ? f->name : ""), node->ino, node->version, | ||
2931 | node->fm->offset, node->data_size)); | ||
2932 | |||
2933 | /* Compute how many data it's possible to rewrite at the moment. */ | ||
2934 | data_size = f->size - node->data_offset; | ||
2935 | |||
2936 | /* And from that, the total size of the chunk we want to write */ | ||
2937 | size = sizeof(struct jffs_raw_inode) + total_name_size | ||
2938 | + data_size + JFFS_GET_PAD_BYTES(data_size); | ||
2939 | |||
2940 | /* If that's more than max_chunk_size, reduce it accordingly */ | ||
2941 | if (size > fmc->max_chunk_size) { | ||
2942 | size = fmc->max_chunk_size; | ||
2943 | data_size = size - sizeof(struct jffs_raw_inode) | ||
2944 | - total_name_size; | ||
2945 | } | ||
2946 | |||
2947 | /* If we're asking to take up more space than free_chunk_size1 | ||
2948 | but we _could_ fit in it, shrink accordingly. | ||
2949 | */ | ||
2950 | if (size > free_chunk_size1) { | ||
2951 | |||
2952 | if (free_chunk_size1 < | ||
2953 | (sizeof(struct jffs_raw_inode) + total_name_size + BLOCK_SIZE)){ | ||
2954 | /* The space left is too small to be of any | ||
2955 | use really. */ | ||
2956 | struct jffs_fm *dirty_fm | ||
2957 | = jffs_fmalloced(fmc, | ||
2958 | fmc->tail->offset + fmc->tail->size, | ||
2959 | free_chunk_size1, NULL); | ||
2960 | if (!dirty_fm) { | ||
2961 | printk(KERN_ERR "JFFS: " | ||
2962 | "jffs_garbage_collect_next: " | ||
2963 | "Failed to allocate `dirty' " | ||
2964 | "flash memory!\n"); | ||
2965 | err = -1; | ||
2966 | goto jffs_garbage_collect_next_end; | ||
2967 | } | ||
2968 | D1(printk("Dirtying end of flash - too small\n")); | ||
2969 | jffs_write_dummy_node(c, dirty_fm); | ||
2970 | err = 0; | ||
2971 | goto jffs_garbage_collect_next_end; | ||
2972 | } | ||
2973 | D1(printk("Reducing size of new node from %d to %d to avoid " | ||
2974 | " exceeding free_chunk_size1\n", | ||
2975 | size, free_chunk_size1)); | ||
2976 | |||
2977 | size = free_chunk_size1; | ||
2978 | data_size = size - sizeof(struct jffs_raw_inode) | ||
2979 | - total_name_size; | ||
2980 | } | ||
2981 | |||
2982 | |||
2983 | /* Calculate the amount of space needed to hold the nodes | ||
2984 | which are remaining in the tail */ | ||
2985 | space_needed = fmc->min_free_size - (node->fm->offset % fmc->sector_size); | ||
2986 | |||
2987 | /* From that, calculate how much 'extra' space we can use to | ||
2988 | increase the size of the node we're writing from the size | ||
2989 | of the node we're obsoleting | ||
2990 | */ | ||
2991 | if (space_needed > fmc->free_size) { | ||
2992 | /* If we've gone below min_free_size for some reason, | ||
2993 | don't fuck up. This is why we have | ||
2994 | min_free_size > sector_size. Whinge about it though, | ||
2995 | just so I can convince myself my maths is right. | ||
2996 | */ | ||
2997 | D1(printk(KERN_WARNING "jffs_garbage_collect_next(): " | ||
2998 | "space_needed %d exceeded free_size %d\n", | ||
2999 | space_needed, fmc->free_size)); | ||
3000 | extra_available = 0; | ||
3001 | } else { | ||
3002 | extra_available = fmc->free_size - space_needed; | ||
3003 | } | ||
3004 | |||
3005 | /* Check that we don't use up any more 'extra' space than | ||
3006 | what's available */ | ||
3007 | if (size > JFFS_PAD(node->data_size) + total_name_size + | ||
3008 | sizeof(struct jffs_raw_inode) + extra_available) { | ||
3009 | D1(printk("Reducing size of new node from %d to %ld to avoid " | ||
3010 | "catching our tail\n", size, | ||
3011 | (long) (JFFS_PAD(node->data_size) + JFFS_PAD(node->name_size) + | ||
3012 | sizeof(struct jffs_raw_inode) + extra_available))); | ||
3013 | D1(printk("space_needed = %d, extra_available = %d\n", | ||
3014 | space_needed, extra_available)); | ||
3015 | |||
3016 | size = JFFS_PAD(node->data_size) + total_name_size + | ||
3017 | sizeof(struct jffs_raw_inode) + extra_available; | ||
3018 | data_size = size - sizeof(struct jffs_raw_inode) | ||
3019 | - total_name_size; | ||
3020 | }; | ||
3021 | |||
3022 | D2(printk(" total_name_size: %u\n", total_name_size)); | ||
3023 | D2(printk(" data_size: %u\n", data_size)); | ||
3024 | D2(printk(" size: %u\n", size)); | ||
3025 | D2(printk(" f->nsize: %u\n", f->nsize)); | ||
3026 | D2(printk(" f->size: %u\n", f->size)); | ||
3027 | D2(printk(" node->data_offset: %u\n", node->data_offset)); | ||
3028 | D2(printk(" free_chunk_size1: %u\n", free_chunk_size1)); | ||
3029 | D2(printk(" free_chunk_size2: %u\n", free_chunk_size2)); | ||
3030 | D2(printk(" node->fm->offset: 0x%08x\n", node->fm->offset)); | ||
3031 | |||
3032 | if ((err = jffs_rewrite_data(f, node, data_size))) { | ||
3033 | printk(KERN_WARNING "jffs_rewrite_data() failed: %d\n", err); | ||
3034 | return err; | ||
3035 | } | ||
3036 | |||
3037 | jffs_garbage_collect_next_end: | ||
3038 | D3(printk("jffs_garbage_collect_next: Leaving...\n")); | ||
3039 | return err; | ||
3040 | } /* jffs_garbage_collect_next */ | ||
3041 | |||
3042 | |||
3043 | /* If an obsolete node is partly going to be erased due to garbage | ||
3044 | collection, the part that isn't going to be erased must be filled | ||
3045 | with zeroes so that the scan of the flash will work smoothly next | ||
3046 | time. (The data in the file could for instance be a JFFS image | ||
3047 | which could cause enormous confusion during a scan of the flash | ||
3048 | device if we didn't do this.) | ||
3049 | There are two phases in this procedure: First, the clearing of | ||
3050 | the name and data parts of the node. Second, possibly also clearing | ||
3051 | a part of the raw inode as well. If the box is power cycled during | ||
3052 | the first phase, only the checksum of this node-to-be-cleared-at- | ||
3053 | the-end will be wrong. If the box is power cycled during, or after, | ||
3054 | the clearing of the raw inode, the information like the length of | ||
3055 | the name and data parts are zeroed. The next time the box is | ||
3056 | powered up, the scanning algorithm manages this faulty data too | ||
3057 | because: | ||
3058 | |||
3059 | - The checksum is invalid and thus the raw inode must be discarded | ||
3060 | in any case. | ||
3061 | - If the lengths of the data part or the name part are zeroed, the | ||
3062 | scanning just continues after the raw inode. But after the inode | ||
3063 | the scanning procedure just finds zeroes which is the same as | ||
3064 | dirt. | ||
3065 | |||
3066 | So, in the end, this could never fail. :-) Even if it does fail, | ||
3067 | the scanning algorithm should manage that too. */ | ||
3068 | |||
3069 | static int | ||
3070 | jffs_clear_end_of_node(struct jffs_control *c, __u32 erase_size) | ||
3071 | { | ||
3072 | struct jffs_fm *fm; | ||
3073 | struct jffs_fmcontrol *fmc = c->fmc; | ||
3074 | __u32 zero_offset; | ||
3075 | __u32 zero_size; | ||
3076 | __u32 zero_offset_data; | ||
3077 | __u32 zero_size_data; | ||
3078 | __u32 cutting_raw_inode = 0; | ||
3079 | |||
3080 | if (!(fm = jffs_cut_node(fmc, erase_size))) { | ||
3081 | D3(printk("jffs_clear_end_of_node(): fm == NULL\n")); | ||
3082 | return 0; | ||
3083 | } | ||
3084 | |||
3085 | /* Where and how much shall we clear? */ | ||
3086 | zero_offset = fmc->head->offset + erase_size; | ||
3087 | zero_size = fm->offset + fm->size - zero_offset; | ||
3088 | |||
3089 | /* Do we have to clear the raw_inode explicitly? */ | ||
3090 | if (fm->size - zero_size < sizeof(struct jffs_raw_inode)) { | ||
3091 | cutting_raw_inode = sizeof(struct jffs_raw_inode) | ||
3092 | - (fm->size - zero_size); | ||
3093 | } | ||
3094 | |||
3095 | /* First, clear the name and data fields. */ | ||
3096 | zero_offset_data = zero_offset + cutting_raw_inode; | ||
3097 | zero_size_data = zero_size - cutting_raw_inode; | ||
3098 | flash_safe_acquire(fmc->mtd); | ||
3099 | flash_memset(fmc->mtd, zero_offset_data, 0, zero_size_data); | ||
3100 | flash_safe_release(fmc->mtd); | ||
3101 | |||
3102 | /* Should we clear a part of the raw inode? */ | ||
3103 | if (cutting_raw_inode) { | ||
3104 | /* I guess it is ok to clear the raw inode in this order. */ | ||
3105 | flash_safe_acquire(fmc->mtd); | ||
3106 | flash_memset(fmc->mtd, zero_offset, 0, | ||
3107 | cutting_raw_inode); | ||
3108 | flash_safe_release(fmc->mtd); | ||
3109 | } | ||
3110 | |||
3111 | return 0; | ||
3112 | } /* jffs_clear_end_of_node() */ | ||
3113 | |||
3114 | /* Try to erase as much as possible of the dirt in the flash memory. */ | ||
3115 | static long | ||
3116 | jffs_try_to_erase(struct jffs_control *c) | ||
3117 | { | ||
3118 | struct jffs_fmcontrol *fmc = c->fmc; | ||
3119 | long erase_size; | ||
3120 | int err; | ||
3121 | __u32 offset; | ||
3122 | |||
3123 | D3(printk("jffs_try_to_erase()\n")); | ||
3124 | |||
3125 | erase_size = jffs_erasable_size(fmc); | ||
3126 | |||
3127 | D2(printk("jffs_try_to_erase(): erase_size = %ld\n", erase_size)); | ||
3128 | |||
3129 | if (erase_size == 0) { | ||
3130 | return 0; | ||
3131 | } | ||
3132 | else if (erase_size < 0) { | ||
3133 | printk(KERN_ERR "JFFS: jffs_try_to_erase: " | ||
3134 | "jffs_erasable_size returned %ld.\n", erase_size); | ||
3135 | return erase_size; | ||
3136 | } | ||
3137 | |||
3138 | if ((err = jffs_clear_end_of_node(c, erase_size)) < 0) { | ||
3139 | printk(KERN_ERR "JFFS: jffs_try_to_erase: " | ||
3140 | "Clearing of node failed.\n"); | ||
3141 | return err; | ||
3142 | } | ||
3143 | |||
3144 | offset = fmc->head->offset; | ||
3145 | |||
3146 | /* Now, let's try to do the erase. */ | ||
3147 | if ((err = flash_erase_region(fmc->mtd, | ||
3148 | offset, erase_size)) < 0) { | ||
3149 | printk(KERN_ERR "JFFS: Erase of flash failed. " | ||
3150 | "offset = %u, erase_size = %ld\n", | ||
3151 | offset, erase_size); | ||
3152 | /* XXX: Here we should allocate this area as dirty | ||
3153 | with jffs_fmalloced or something similar. Now | ||
3154 | we just report the error. */ | ||
3155 | return err; | ||
3156 | } | ||
3157 | |||
3158 | #if 0 | ||
3159 | /* Check if the erased sectors really got erased. */ | ||
3160 | { | ||
3161 | __u32 pos; | ||
3162 | __u32 end; | ||
3163 | |||
3164 | pos = (__u32)flash_get_direct_pointer(to_kdev_t(c->sb->s_dev), offset); | ||
3165 | end = pos + erase_size; | ||
3166 | |||
3167 | D2(printk("JFFS: Checking erased sector(s)...\n")); | ||
3168 | |||
3169 | flash_safe_acquire(fmc->mtd); | ||
3170 | |||
3171 | for (; pos < end; pos += 4) { | ||
3172 | if (*(__u32 *)pos != JFFS_EMPTY_BITMASK) { | ||
3173 | printk("JFFS: Erase failed! pos = 0x%lx\n", | ||
3174 | (long)pos); | ||
3175 | jffs_hexdump(fmc->mtd, pos, | ||
3176 | jffs_min(256, end - pos)); | ||
3177 | err = -1; | ||
3178 | break; | ||
3179 | } | ||
3180 | } | ||
3181 | |||
3182 | flash_safe_release(fmc->mtd); | ||
3183 | |||
3184 | if (!err) { | ||
3185 | D2(printk("JFFS: Erase succeeded.\n")); | ||
3186 | } | ||
3187 | else { | ||
3188 | /* XXX: Here we should allocate the memory | ||
3189 | with jffs_fmalloced() in order to prevent | ||
3190 | JFFS from using this area accidentally. */ | ||
3191 | return err; | ||
3192 | } | ||
3193 | } | ||
3194 | #endif | ||
3195 | |||
3196 | /* Update the flash memory data structures. */ | ||
3197 | jffs_sync_erase(fmc, erase_size); | ||
3198 | |||
3199 | return erase_size; | ||
3200 | } | ||
3201 | |||
3202 | |||
3203 | /* There are different criteria that should trigger a garbage collect: | ||
3204 | |||
3205 | 1. There is too much dirt in the memory. | ||
3206 | 2. The free space is becoming small. | ||
3207 | 3. There are many versions of a node. | ||
3208 | |||
3209 | The garbage collect should always be done in a manner that guarantees | ||
3210 | that future garbage collects cannot be locked. E.g. Rewritten chunks | ||
3211 | should not be too large (span more than one sector in the flash memory | ||
3212 | for exemple). Of course there is a limit on how intelligent this garbage | ||
3213 | collection can be. */ | ||
3214 | |||
3215 | |||
3216 | static int | ||
3217 | jffs_garbage_collect_now(struct jffs_control *c) | ||
3218 | { | ||
3219 | struct jffs_fmcontrol *fmc = c->fmc; | ||
3220 | long erased = 0; | ||
3221 | int result = 0; | ||
3222 | D1(int i = 1); | ||
3223 | D2(printk("***jffs_garbage_collect_now(): fmc->dirty_size = %u, fmc->free_size = 0x%x\n, fcs1=0x%x, fcs2=0x%x", | ||
3224 | fmc->dirty_size, fmc->free_size, jffs_free_size1(fmc), jffs_free_size2(fmc))); | ||
3225 | D2(jffs_print_fmcontrol(fmc)); | ||
3226 | |||
3227 | // down(&fmc->gclock); | ||
3228 | |||
3229 | /* If it is possible to garbage collect, do so. */ | ||
3230 | |||
3231 | while (erased == 0) { | ||
3232 | D1(printk("***jffs_garbage_collect_now(): round #%u, " | ||
3233 | "fmc->dirty_size = %u\n", i++, fmc->dirty_size)); | ||
3234 | D2(jffs_print_fmcontrol(fmc)); | ||
3235 | |||
3236 | if ((erased = jffs_try_to_erase(c)) < 0) { | ||
3237 | printk(KERN_WARNING "JFFS: Error in " | ||
3238 | "garbage collector.\n"); | ||
3239 | result = erased; | ||
3240 | goto gc_end; | ||
3241 | } | ||
3242 | if (erased) | ||
3243 | break; | ||
3244 | |||
3245 | if (fmc->free_size == 0) { | ||
3246 | /* Argh */ | ||
3247 | printk(KERN_ERR "jffs_garbage_collect_now(): free_size == 0. This is BAD.\n"); | ||
3248 | result = -ENOSPC; | ||
3249 | break; | ||
3250 | } | ||
3251 | |||
3252 | if (fmc->dirty_size < fmc->sector_size) { | ||
3253 | /* Actually, we _may_ have been able to free some, | ||
3254 | * if there are many overlapping nodes which aren't | ||
3255 | * actually marked dirty because they still have | ||
3256 | * some valid data in each. | ||
3257 | */ | ||
3258 | result = -ENOSPC; | ||
3259 | break; | ||
3260 | } | ||
3261 | |||
3262 | /* Let's dare to make a garbage collect. */ | ||
3263 | if ((result = jffs_garbage_collect_next(c)) < 0) { | ||
3264 | printk(KERN_ERR "JFFS: Something " | ||
3265 | "has gone seriously wrong " | ||
3266 | "with a garbage collect.\n"); | ||
3267 | goto gc_end; | ||
3268 | } | ||
3269 | |||
3270 | D1(printk(" jffs_garbage_collect_now(): erased: %ld\n", erased)); | ||
3271 | DJM(jffs_print_memory_allocation_statistics()); | ||
3272 | } | ||
3273 | |||
3274 | gc_end: | ||
3275 | // up(&fmc->gclock); | ||
3276 | |||
3277 | D3(printk(" jffs_garbage_collect_now(): Leaving...\n")); | ||
3278 | D1(if (erased) { | ||
3279 | printk("jffs_g_c_now(): erased = %ld\n", erased); | ||
3280 | jffs_print_fmcontrol(fmc); | ||
3281 | }); | ||
3282 | |||
3283 | if (!erased && !result) | ||
3284 | return -ENOSPC; | ||
3285 | |||
3286 | return result; | ||
3287 | } /* jffs_garbage_collect_now() */ | ||
3288 | |||
3289 | |||
3290 | /* Determine if it is reasonable to start garbage collection. | ||
3291 | We start a gc pass if either: | ||
3292 | - The number of free bytes < MIN_FREE_BYTES && at least one | ||
3293 | block is dirty, OR | ||
3294 | - The number of dirty bytes > MAX_DIRTY_BYTES | ||
3295 | */ | ||
3296 | static inline int thread_should_wake (struct jffs_control *c) | ||
3297 | { | ||
3298 | D1(printk (KERN_NOTICE "thread_should_wake(): free=%d, dirty=%d, blocksize=%d.\n", | ||
3299 | c->fmc->free_size, c->fmc->dirty_size, c->fmc->sector_size)); | ||
3300 | |||
3301 | /* If there's not enough dirty space to free a block, there's no point. */ | ||
3302 | if (c->fmc->dirty_size < c->fmc->sector_size) { | ||
3303 | D2(printk(KERN_NOTICE "thread_should_wake(): Not waking. Insufficient dirty space\n")); | ||
3304 | return 0; | ||
3305 | } | ||
3306 | #if 1 | ||
3307 | /* If there is too much RAM used by the various structures, GC */ | ||
3308 | if (jffs_get_node_inuse() > (c->fmc->used_size/c->fmc->max_chunk_size * 5 + jffs_get_file_count() * 2 + 50)) { | ||
3309 | /* FIXME: Provide proof that this test can be satisfied. We | ||
3310 | don't want a filesystem doing endless GC just because this | ||
3311 | condition cannot ever be false. | ||
3312 | */ | ||
3313 | D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to number of nodes\n")); | ||
3314 | return 1; | ||
3315 | } | ||
3316 | #endif | ||
3317 | /* If there are fewer free bytes than the threshold, GC */ | ||
3318 | if (c->fmc->free_size < c->gc_minfree_threshold) { | ||
3319 | D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to insufficent free space\n")); | ||
3320 | return 1; | ||
3321 | } | ||
3322 | /* If there are more dirty bytes than the threshold, GC */ | ||
3323 | if (c->fmc->dirty_size > c->gc_maxdirty_threshold) { | ||
3324 | D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to excessive dirty space\n")); | ||
3325 | return 1; | ||
3326 | } | ||
3327 | /* FIXME: What about the "There are many versions of a node" condition? */ | ||
3328 | |||
3329 | return 0; | ||
3330 | } | ||
3331 | |||
3332 | |||
3333 | void jffs_garbage_collect_trigger(struct jffs_control *c) | ||
3334 | { | ||
3335 | /* NOTE: We rely on the fact that we have the BKL here. | ||
3336 | * Otherwise, the gc_task could go away between the check | ||
3337 | * and the wake_up_process() | ||
3338 | */ | ||
3339 | if (c->gc_task && thread_should_wake(c)) | ||
3340 | send_sig(SIGHUP, c->gc_task, 1); | ||
3341 | } | ||
3342 | |||
3343 | |||
3344 | /* Kernel threads take (void *) as arguments. Thus we pass | ||
3345 | the jffs_control data as a (void *) and then cast it. */ | ||
3346 | int | ||
3347 | jffs_garbage_collect_thread(void *ptr) | ||
3348 | { | ||
3349 | struct jffs_control *c = (struct jffs_control *) ptr; | ||
3350 | struct jffs_fmcontrol *fmc = c->fmc; | ||
3351 | long erased; | ||
3352 | int result = 0; | ||
3353 | D1(int i = 1); | ||
3354 | |||
3355 | daemonize("jffs_gcd"); | ||
3356 | |||
3357 | c->gc_task = current; | ||
3358 | |||
3359 | lock_kernel(); | ||
3360 | init_completion(&c->gc_thread_comp); /* barrier */ | ||
3361 | spin_lock_irq(¤t->sighand->siglock); | ||
3362 | siginitsetinv (¤t->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); | ||
3363 | recalc_sigpending(); | ||
3364 | spin_unlock_irq(¤t->sighand->siglock); | ||
3365 | |||
3366 | D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): Starting infinite loop.\n")); | ||
3367 | |||
3368 | for (;;) { | ||
3369 | |||
3370 | /* See if we need to start gc. If we don't, go to sleep. | ||
3371 | |||
3372 | Current implementation is a BAD THING(tm). If we try | ||
3373 | to unmount the FS, the unmount operation will sleep waiting | ||
3374 | for this thread to exit. We need to arrange to send it a | ||
3375 | sig before the umount process sleeps. | ||
3376 | */ | ||
3377 | |||
3378 | if (!thread_should_wake(c)) | ||
3379 | set_current_state (TASK_INTERRUPTIBLE); | ||
3380 | |||
3381 | schedule(); /* Yes, we do this even if we want to go | ||
3382 | on immediately - we're a low priority | ||
3383 | background task. */ | ||
3384 | |||
3385 | /* Put_super will send a SIGKILL and then wait on the sem. | ||
3386 | */ | ||
3387 | while (signal_pending(current)) { | ||
3388 | siginfo_t info; | ||
3389 | unsigned long signr = 0; | ||
3390 | |||
3391 | if (try_to_freeze()) | ||
3392 | continue; | ||
3393 | |||
3394 | spin_lock_irq(¤t->sighand->siglock); | ||
3395 | signr = dequeue_signal(current, ¤t->blocked, &info); | ||
3396 | spin_unlock_irq(¤t->sighand->siglock); | ||
3397 | |||
3398 | switch(signr) { | ||
3399 | case SIGSTOP: | ||
3400 | D1(printk("jffs_garbage_collect_thread(): SIGSTOP received.\n")); | ||
3401 | set_current_state(TASK_STOPPED); | ||
3402 | schedule(); | ||
3403 | break; | ||
3404 | |||
3405 | case SIGKILL: | ||
3406 | D1(printk("jffs_garbage_collect_thread(): SIGKILL received.\n")); | ||
3407 | c->gc_task = NULL; | ||
3408 | complete_and_exit(&c->gc_thread_comp, 0); | ||
3409 | } | ||
3410 | } | ||
3411 | |||
3412 | |||
3413 | D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): collecting.\n")); | ||
3414 | |||
3415 | D3(printk (KERN_NOTICE "g_c_thread(): down biglock\n")); | ||
3416 | mutex_lock(&fmc->biglock); | ||
3417 | |||
3418 | D1(printk("***jffs_garbage_collect_thread(): round #%u, " | ||
3419 | "fmc->dirty_size = %u\n", i++, fmc->dirty_size)); | ||
3420 | D2(jffs_print_fmcontrol(fmc)); | ||
3421 | |||
3422 | if ((erased = jffs_try_to_erase(c)) < 0) { | ||
3423 | printk(KERN_WARNING "JFFS: Error in " | ||
3424 | "garbage collector: %ld.\n", erased); | ||
3425 | } | ||
3426 | |||
3427 | if (erased) | ||
3428 | goto gc_end; | ||
3429 | |||
3430 | if (fmc->free_size == 0) { | ||
3431 | /* Argh. Might as well commit suicide. */ | ||
3432 | printk(KERN_ERR "jffs_garbage_collect_thread(): free_size == 0. This is BAD.\n"); | ||
3433 | send_sig(SIGQUIT, c->gc_task, 1); | ||
3434 | // panic() | ||
3435 | goto gc_end; | ||
3436 | } | ||
3437 | |||
3438 | /* Let's dare to make a garbage collect. */ | ||
3439 | if ((result = jffs_garbage_collect_next(c)) < 0) { | ||
3440 | printk(KERN_ERR "JFFS: Something " | ||
3441 | "has gone seriously wrong " | ||
3442 | "with a garbage collect: %d\n", result); | ||
3443 | } | ||
3444 | |||
3445 | gc_end: | ||
3446 | D3(printk (KERN_NOTICE "g_c_thread(): up biglock\n")); | ||
3447 | mutex_unlock(&fmc->biglock); | ||
3448 | } /* for (;;) */ | ||
3449 | } /* jffs_garbage_collect_thread() */ | ||
diff --git a/fs/jffs/intrep.h b/fs/jffs/intrep.h deleted file mode 100644 index 5c7abe0e2695..000000000000 --- a/fs/jffs/intrep.h +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /* | ||
2 | * JFFS -- Journaling Flash File System, Linux implementation. | ||
3 | * | ||
4 | * Copyright (C) 1999, 2000 Axis Communications AB. | ||
5 | * | ||
6 | * Created by Finn Hakansson <finn@axis.com>. | ||
7 | * | ||
8 | * This is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * $Id: intrep.h,v 1.14 2001/09/23 23:28:37 dwmw2 Exp $ | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __LINUX_JFFS_INTREP_H__ | ||
18 | #define __LINUX_JFFS_INTREP_H__ | ||
19 | #include "jffs_fm.h" | ||
20 | struct jffs_node *jffs_alloc_node(void); | ||
21 | void jffs_free_node(struct jffs_node *n); | ||
22 | int jffs_get_node_inuse(void); | ||
23 | |||
24 | void jffs_cleanup_control(struct jffs_control *c); | ||
25 | int jffs_build_fs(struct super_block *sb); | ||
26 | |||
27 | int jffs_insert_node(struct jffs_control *c, struct jffs_file *f, | ||
28 | const struct jffs_raw_inode *raw_inode, | ||
29 | const char *name, struct jffs_node *node); | ||
30 | struct jffs_file *jffs_find_file(struct jffs_control *c, __u32 ino); | ||
31 | struct jffs_file *jffs_find_child(struct jffs_file *dir, const char *name, int len); | ||
32 | |||
33 | void jffs_free_node(struct jffs_node *node); | ||
34 | |||
35 | int jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *)); | ||
36 | int jffs_possibly_delete_file(struct jffs_file *f); | ||
37 | int jffs_insert_file_into_tree(struct jffs_file *f); | ||
38 | int jffs_unlink_file_from_tree(struct jffs_file *f); | ||
39 | int jffs_file_count(struct jffs_file *f); | ||
40 | |||
41 | int jffs_write_node(struct jffs_control *c, struct jffs_node *node, | ||
42 | struct jffs_raw_inode *raw_inode, | ||
43 | const char *name, const unsigned char *buf, | ||
44 | int recoverable, struct jffs_file *f); | ||
45 | int jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset, __u32 size); | ||
46 | |||
47 | /* Garbage collection stuff. */ | ||
48 | int jffs_garbage_collect_thread(void *c); | ||
49 | void jffs_garbage_collect_trigger(struct jffs_control *c); | ||
50 | |||
51 | /* For debugging purposes. */ | ||
52 | #if 0 | ||
53 | int jffs_print_file(struct jffs_file *f); | ||
54 | #endif /* 0 */ | ||
55 | void jffs_print_hash_table(struct jffs_control *c); | ||
56 | void jffs_print_tree(struct jffs_file *first_file, int indent); | ||
57 | |||
58 | #endif /* __LINUX_JFFS_INTREP_H__ */ | ||
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c deleted file mode 100644 index 5a95fbdd6fdb..000000000000 --- a/fs/jffs/jffs_fm.c +++ /dev/null | |||
@@ -1,798 +0,0 @@ | |||
1 | /* | ||
2 | * JFFS -- Journaling Flash File System, Linux implementation. | ||
3 | * | ||
4 | * Copyright (C) 1999, 2000 Axis Communications AB. | ||
5 | * | ||
6 | * Created by Finn Hakansson <finn@axis.com>. | ||
7 | * | ||
8 | * This is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $ | ||
14 | * | ||
15 | * Ported to Linux 2.3.x and MTD: | ||
16 | * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/blkdev.h> | ||
22 | #include <linux/jffs.h> | ||
23 | #include "jffs_fm.h" | ||
24 | #include "intrep.h" | ||
25 | |||
26 | #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE | ||
27 | static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset); | ||
28 | #endif | ||
29 | |||
30 | static struct jffs_fm *jffs_alloc_fm(void); | ||
31 | static void jffs_free_fm(struct jffs_fm *n); | ||
32 | |||
33 | extern struct kmem_cache *fm_cache; | ||
34 | extern struct kmem_cache *node_cache; | ||
35 | |||
36 | #if CONFIG_JFFS_FS_VERBOSE > 0 | ||
37 | void | ||
38 | jffs_print_fmcontrol(struct jffs_fmcontrol *fmc) | ||
39 | { | ||
40 | D(printk("struct jffs_fmcontrol: 0x%p\n", fmc)); | ||
41 | D(printk("{\n")); | ||
42 | D(printk(" %u, /* flash_size */\n", fmc->flash_size)); | ||
43 | D(printk(" %u, /* used_size */\n", fmc->used_size)); | ||
44 | D(printk(" %u, /* dirty_size */\n", fmc->dirty_size)); | ||
45 | D(printk(" %u, /* free_size */\n", fmc->free_size)); | ||
46 | D(printk(" %u, /* sector_size */\n", fmc->sector_size)); | ||
47 | D(printk(" %u, /* min_free_size */\n", fmc->min_free_size)); | ||
48 | D(printk(" %u, /* max_chunk_size */\n", fmc->max_chunk_size)); | ||
49 | D(printk(" 0x%p, /* mtd */\n", fmc->mtd)); | ||
50 | D(printk(" 0x%p, /* head */ " | ||
51 | "(head->offset = 0x%08x)\n", | ||
52 | fmc->head, (fmc->head ? fmc->head->offset : 0))); | ||
53 | D(printk(" 0x%p, /* tail */ " | ||
54 | "(tail->offset + tail->size = 0x%08x)\n", | ||
55 | fmc->tail, | ||
56 | (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0))); | ||
57 | D(printk(" 0x%p, /* head_extra */\n", fmc->head_extra)); | ||
58 | D(printk(" 0x%p, /* tail_extra */\n", fmc->tail_extra)); | ||
59 | D(printk("}\n")); | ||
60 | } | ||
61 | #endif /* CONFIG_JFFS_FS_VERBOSE > 0 */ | ||
62 | |||
63 | #if CONFIG_JFFS_FS_VERBOSE > 2 | ||
64 | static void | ||
65 | jffs_print_fm(struct jffs_fm *fm) | ||
66 | { | ||
67 | D(printk("struct jffs_fm: 0x%p\n", fm)); | ||
68 | D(printk("{\n")); | ||
69 | D(printk(" 0x%08x, /* offset */\n", fm->offset)); | ||
70 | D(printk(" %u, /* size */\n", fm->size)); | ||
71 | D(printk(" 0x%p, /* prev */\n", fm->prev)); | ||
72 | D(printk(" 0x%p, /* next */\n", fm->next)); | ||
73 | D(printk(" 0x%p, /* nodes */\n", fm->nodes)); | ||
74 | D(printk("}\n")); | ||
75 | } | ||
76 | #endif /* CONFIG_JFFS_FS_VERBOSE > 2 */ | ||
77 | |||
78 | #if 0 | ||
79 | void | ||
80 | jffs_print_node_ref(struct jffs_node_ref *ref) | ||
81 | { | ||
82 | D(printk("struct jffs_node_ref: 0x%p\n", ref)); | ||
83 | D(printk("{\n")); | ||
84 | D(printk(" 0x%p, /* node */\n", ref->node)); | ||
85 | D(printk(" 0x%p, /* next */\n", ref->next)); | ||
86 | D(printk("}\n")); | ||
87 | } | ||
88 | #endif /* 0 */ | ||
89 | |||
90 | /* This function creates a new shiny flash memory control structure. */ | ||
91 | struct jffs_fmcontrol * | ||
92 | jffs_build_begin(struct jffs_control *c, int unit) | ||
93 | { | ||
94 | struct jffs_fmcontrol *fmc; | ||
95 | struct mtd_info *mtd; | ||
96 | |||
97 | D3(printk("jffs_build_begin()\n")); | ||
98 | fmc = kmalloc(sizeof(*fmc), GFP_KERNEL); | ||
99 | if (!fmc) { | ||
100 | D(printk("jffs_build_begin(): Allocation of " | ||
101 | "struct jffs_fmcontrol failed!\n")); | ||
102 | return (struct jffs_fmcontrol *)0; | ||
103 | } | ||
104 | DJM(no_jffs_fmcontrol++); | ||
105 | |||
106 | mtd = get_mtd_device(NULL, unit); | ||
107 | |||
108 | if (IS_ERR(mtd)) { | ||
109 | kfree(fmc); | ||
110 | DJM(no_jffs_fmcontrol--); | ||
111 | return NULL; | ||
112 | } | ||
113 | |||
114 | /* Retrieve the size of the flash memory. */ | ||
115 | fmc->flash_size = mtd->size; | ||
116 | D3(printk(" fmc->flash_size = %d bytes\n", fmc->flash_size)); | ||
117 | |||
118 | fmc->used_size = 0; | ||
119 | fmc->dirty_size = 0; | ||
120 | fmc->free_size = mtd->size; | ||
121 | fmc->sector_size = mtd->erasesize; | ||
122 | fmc->max_chunk_size = fmc->sector_size >> 1; | ||
123 | /* min_free_size: | ||
124 | 1 sector, obviously. | ||
125 | + 1 x max_chunk_size, for when a nodes overlaps the end of a sector | ||
126 | + 1 x max_chunk_size again, which ought to be enough to handle | ||
127 | the case where a rename causes a name to grow, and GC has | ||
128 | to write out larger nodes than the ones it's obsoleting. | ||
129 | We should fix it so it doesn't have to write the name | ||
130 | _every_ time. Later. | ||
131 | + another 2 sectors because people keep getting GC stuck and | ||
132 | we don't know why. This scares me - I want formal proof | ||
133 | of correctness of whatever number we put here. dwmw2. | ||
134 | */ | ||
135 | fmc->min_free_size = fmc->sector_size << 2; | ||
136 | fmc->mtd = mtd; | ||
137 | fmc->c = c; | ||
138 | fmc->head = NULL; | ||
139 | fmc->tail = NULL; | ||
140 | fmc->head_extra = NULL; | ||
141 | fmc->tail_extra = NULL; | ||
142 | mutex_init(&fmc->biglock); | ||
143 | return fmc; | ||
144 | } | ||
145 | |||
146 | |||
147 | /* When the flash memory scan has completed, this function should be called | ||
148 | before use of the control structure. */ | ||
149 | void | ||
150 | jffs_build_end(struct jffs_fmcontrol *fmc) | ||
151 | { | ||
152 | D3(printk("jffs_build_end()\n")); | ||
153 | |||
154 | if (!fmc->head) { | ||
155 | fmc->head = fmc->head_extra; | ||
156 | fmc->tail = fmc->tail_extra; | ||
157 | } | ||
158 | else if (fmc->head_extra) { | ||
159 | fmc->tail_extra->next = fmc->head; | ||
160 | fmc->head->prev = fmc->tail_extra; | ||
161 | fmc->head = fmc->head_extra; | ||
162 | } | ||
163 | fmc->head_extra = NULL; /* These two instructions should be omitted. */ | ||
164 | fmc->tail_extra = NULL; | ||
165 | D3(jffs_print_fmcontrol(fmc)); | ||
166 | } | ||
167 | |||
168 | |||
169 | /* Call this function when the file system is unmounted. This function | ||
170 | frees all memory used by this module. */ | ||
171 | void | ||
172 | jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc) | ||
173 | { | ||
174 | if (fmc) { | ||
175 | struct jffs_fm *next = fmc->head; | ||
176 | while (next) { | ||
177 | struct jffs_fm *cur = next; | ||
178 | next = next->next; | ||
179 | jffs_free_fm(cur); | ||
180 | } | ||
181 | put_mtd_device(fmc->mtd); | ||
182 | kfree(fmc); | ||
183 | DJM(no_jffs_fmcontrol--); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | |||
188 | /* This function returns the size of the first chunk of free space on the | ||
189 | flash memory. This function will return something nonzero if the flash | ||
190 | memory contains any free space. */ | ||
191 | __u32 | ||
192 | jffs_free_size1(struct jffs_fmcontrol *fmc) | ||
193 | { | ||
194 | __u32 head; | ||
195 | __u32 tail; | ||
196 | __u32 end = fmc->flash_size; | ||
197 | |||
198 | if (!fmc->head) { | ||
199 | /* There is nothing on the flash. */ | ||
200 | return fmc->flash_size; | ||
201 | } | ||
202 | |||
203 | /* Compute the beginning and ending of the contents of the flash. */ | ||
204 | head = fmc->head->offset; | ||
205 | tail = fmc->tail->offset + fmc->tail->size; | ||
206 | if (tail == end) { | ||
207 | tail = 0; | ||
208 | } | ||
209 | ASSERT(else if (tail > end) { | ||
210 | printk(KERN_WARNING "jffs_free_size1(): tail > end\n"); | ||
211 | tail = 0; | ||
212 | }); | ||
213 | |||
214 | if (head <= tail) { | ||
215 | return end - tail; | ||
216 | } | ||
217 | else { | ||
218 | return head - tail; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | /* This function will return something nonzero in case there are two free | ||
223 | areas on the flash. Like this: | ||
224 | |||
225 | +----------------+------------------+----------------+ | ||
226 | | FREE 1 | USED / DIRTY | FREE 2 | | ||
227 | +----------------+------------------+----------------+ | ||
228 | fmc->head -----^ | ||
229 | fmc->tail ------------------------^ | ||
230 | |||
231 | The value returned, will be the size of the first empty area on the | ||
232 | flash, in this case marked "FREE 1". */ | ||
233 | __u32 | ||
234 | jffs_free_size2(struct jffs_fmcontrol *fmc) | ||
235 | { | ||
236 | if (fmc->head) { | ||
237 | __u32 head = fmc->head->offset; | ||
238 | __u32 tail = fmc->tail->offset + fmc->tail->size; | ||
239 | if (tail == fmc->flash_size) { | ||
240 | tail = 0; | ||
241 | } | ||
242 | |||
243 | if (tail >= head) { | ||
244 | return head; | ||
245 | } | ||
246 | } | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | |||
251 | /* Allocate a chunk of flash memory. If there is enough space on the | ||
252 | device, a reference to the associated node is stored in the jffs_fm | ||
253 | struct. */ | ||
254 | int | ||
255 | jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node, | ||
256 | struct jffs_fm **result) | ||
257 | { | ||
258 | struct jffs_fm *fm; | ||
259 | __u32 free_chunk_size1; | ||
260 | __u32 free_chunk_size2; | ||
261 | |||
262 | D2(printk("jffs_fmalloc(): fmc = 0x%p, size = %d, " | ||
263 | "node = 0x%p\n", fmc, size, node)); | ||
264 | |||
265 | *result = NULL; | ||
266 | |||
267 | if (!(fm = jffs_alloc_fm())) { | ||
268 | D(printk("jffs_fmalloc(): kmalloc() failed! (fm)\n")); | ||
269 | return -ENOMEM; | ||
270 | } | ||
271 | |||
272 | free_chunk_size1 = jffs_free_size1(fmc); | ||
273 | free_chunk_size2 = jffs_free_size2(fmc); | ||
274 | if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) { | ||
275 | printk(KERN_WARNING "Free size accounting screwed\n"); | ||
276 | printk(KERN_WARNING "free_chunk_size1 == 0x%x, free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", free_chunk_size1, free_chunk_size2, fmc->free_size); | ||
277 | } | ||
278 | |||
279 | D3(printk("jffs_fmalloc(): free_chunk_size1 = %u, " | ||
280 | "free_chunk_size2 = %u\n", | ||
281 | free_chunk_size1, free_chunk_size2)); | ||
282 | |||
283 | if (size <= free_chunk_size1) { | ||
284 | if (!(fm->nodes = (struct jffs_node_ref *) | ||
285 | kmalloc(sizeof(struct jffs_node_ref), | ||
286 | GFP_KERNEL))) { | ||
287 | D(printk("jffs_fmalloc(): kmalloc() failed! " | ||
288 | "(node_ref)\n")); | ||
289 | jffs_free_fm(fm); | ||
290 | return -ENOMEM; | ||
291 | } | ||
292 | DJM(no_jffs_node_ref++); | ||
293 | fm->nodes->node = node; | ||
294 | fm->nodes->next = NULL; | ||
295 | if (fmc->tail) { | ||
296 | fm->offset = fmc->tail->offset + fmc->tail->size; | ||
297 | if (fm->offset == fmc->flash_size) { | ||
298 | fm->offset = 0; | ||
299 | } | ||
300 | ASSERT(else if (fm->offset > fmc->flash_size) { | ||
301 | printk(KERN_WARNING "jffs_fmalloc(): " | ||
302 | "offset > flash_end\n"); | ||
303 | fm->offset = 0; | ||
304 | }); | ||
305 | } | ||
306 | else { | ||
307 | /* There don't have to be files in the file | ||
308 | system yet. */ | ||
309 | fm->offset = 0; | ||
310 | } | ||
311 | fm->size = size; | ||
312 | fmc->free_size -= size; | ||
313 | fmc->used_size += size; | ||
314 | } | ||
315 | else if (size > free_chunk_size2) { | ||
316 | printk(KERN_WARNING "JFFS: Tried to allocate a too " | ||
317 | "large flash memory chunk. (size = %u)\n", size); | ||
318 | jffs_free_fm(fm); | ||
319 | return -ENOSPC; | ||
320 | } | ||
321 | else { | ||
322 | fm->offset = fmc->tail->offset + fmc->tail->size; | ||
323 | fm->size = free_chunk_size1; | ||
324 | fm->nodes = NULL; | ||
325 | fmc->free_size -= fm->size; | ||
326 | fmc->dirty_size += fm->size; /* Changed by simonk. This seemingly fixes a | ||
327 | bug that caused infinite garbage collection. | ||
328 | It previously set fmc->dirty_size to size (which is the | ||
329 | size of the requested chunk). | ||
330 | */ | ||
331 | } | ||
332 | |||
333 | fm->next = NULL; | ||
334 | if (!fmc->head) { | ||
335 | fm->prev = NULL; | ||
336 | fmc->head = fm; | ||
337 | fmc->tail = fm; | ||
338 | } | ||
339 | else { | ||
340 | fm->prev = fmc->tail; | ||
341 | fmc->tail->next = fm; | ||
342 | fmc->tail = fm; | ||
343 | } | ||
344 | |||
345 | D3(jffs_print_fmcontrol(fmc)); | ||
346 | D3(jffs_print_fm(fm)); | ||
347 | *result = fm; | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | |||
352 | /* The on-flash space is not needed anymore by the passed node. Remove | ||
353 | the reference to the node from the node list. If the data chunk in | ||
354 | the flash memory isn't used by any more nodes anymore (fm->nodes == 0), | ||
355 | then mark that chunk as dirty. */ | ||
356 | int | ||
357 | jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, struct jffs_node *node) | ||
358 | { | ||
359 | struct jffs_node_ref *ref; | ||
360 | struct jffs_node_ref *prev; | ||
361 | ASSERT(int del = 0); | ||
362 | |||
363 | D2(printk("jffs_fmfree(): node->ino = %u, node->version = %u\n", | ||
364 | node->ino, node->version)); | ||
365 | |||
366 | ASSERT(if (!fmc || !fm || !fm->nodes) { | ||
367 | printk(KERN_ERR "jffs_fmfree(): fmc: 0x%p, fm: 0x%p, " | ||
368 | "fm->nodes: 0x%p\n", | ||
369 | fmc, fm, (fm ? fm->nodes : NULL)); | ||
370 | return -1; | ||
371 | }); | ||
372 | |||
373 | /* Find the reference to the node that is going to be removed | ||
374 | and remove it. */ | ||
375 | for (ref = fm->nodes, prev = NULL; ref; ref = ref->next) { | ||
376 | if (ref->node == node) { | ||
377 | if (prev) { | ||
378 | prev->next = ref->next; | ||
379 | } | ||
380 | else { | ||
381 | fm->nodes = ref->next; | ||
382 | } | ||
383 | kfree(ref); | ||
384 | DJM(no_jffs_node_ref--); | ||
385 | ASSERT(del = 1); | ||
386 | break; | ||
387 | } | ||
388 | prev = ref; | ||
389 | } | ||
390 | |||
391 | /* If the data chunk in the flash memory isn't used anymore | ||
392 | just mark it as obsolete. */ | ||
393 | if (!fm->nodes) { | ||
394 | /* No node uses this chunk so let's remove it. */ | ||
395 | fmc->used_size -= fm->size; | ||
396 | fmc->dirty_size += fm->size; | ||
397 | #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE | ||
398 | if (jffs_mark_obsolete(fmc, fm->offset) < 0) { | ||
399 | D1(printk("jffs_fmfree(): Failed to mark an on-flash " | ||
400 | "node obsolete!\n")); | ||
401 | return -1; | ||
402 | } | ||
403 | #endif | ||
404 | } | ||
405 | |||
406 | ASSERT(if (!del) { | ||
407 | printk(KERN_WARNING "***jffs_fmfree(): " | ||
408 | "Didn't delete any node reference!\n"); | ||
409 | }); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | |||
415 | /* This allocation function is used during the initialization of | ||
416 | the file system. */ | ||
417 | struct jffs_fm * | ||
418 | jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size, | ||
419 | struct jffs_node *node) | ||
420 | { | ||
421 | struct jffs_fm *fm; | ||
422 | |||
423 | D3(printk("jffs_fmalloced()\n")); | ||
424 | |||
425 | if (!(fm = jffs_alloc_fm())) { | ||
426 | D(printk("jffs_fmalloced(0x%p, %u, %u, 0x%p): failed!\n", | ||
427 | fmc, offset, size, node)); | ||
428 | return NULL; | ||
429 | } | ||
430 | fm->offset = offset; | ||
431 | fm->size = size; | ||
432 | fm->prev = NULL; | ||
433 | fm->next = NULL; | ||
434 | fm->nodes = NULL; | ||
435 | if (node) { | ||
436 | /* `node' exists and it should be associated with the | ||
437 | jffs_fm structure `fm'. */ | ||
438 | if (!(fm->nodes = (struct jffs_node_ref *) | ||
439 | kmalloc(sizeof(struct jffs_node_ref), | ||
440 | GFP_KERNEL))) { | ||
441 | D(printk("jffs_fmalloced(): !fm->nodes\n")); | ||
442 | jffs_free_fm(fm); | ||
443 | return NULL; | ||
444 | } | ||
445 | DJM(no_jffs_node_ref++); | ||
446 | fm->nodes->node = node; | ||
447 | fm->nodes->next = NULL; | ||
448 | fmc->used_size += size; | ||
449 | fmc->free_size -= size; | ||
450 | } | ||
451 | else { | ||
452 | /* If there is no node, then this is just a chunk of dirt. */ | ||
453 | fmc->dirty_size += size; | ||
454 | fmc->free_size -= size; | ||
455 | } | ||
456 | |||
457 | if (fmc->head_extra) { | ||
458 | fm->prev = fmc->tail_extra; | ||
459 | fmc->tail_extra->next = fm; | ||
460 | fmc->tail_extra = fm; | ||
461 | } | ||
462 | else if (!fmc->head) { | ||
463 | fmc->head = fm; | ||
464 | fmc->tail = fm; | ||
465 | } | ||
466 | else if (fmc->tail->offset + fmc->tail->size < offset) { | ||
467 | fmc->head_extra = fm; | ||
468 | fmc->tail_extra = fm; | ||
469 | } | ||
470 | else { | ||
471 | fm->prev = fmc->tail; | ||
472 | fmc->tail->next = fm; | ||
473 | fmc->tail = fm; | ||
474 | } | ||
475 | D3(jffs_print_fmcontrol(fmc)); | ||
476 | D3(jffs_print_fm(fm)); | ||
477 | return fm; | ||
478 | } | ||
479 | |||
480 | |||
481 | /* Add a new node to an already existing jffs_fm struct. */ | ||
482 | int | ||
483 | jffs_add_node(struct jffs_node *node) | ||
484 | { | ||
485 | struct jffs_node_ref *ref; | ||
486 | |||
487 | D3(printk("jffs_add_node(): ino = %u\n", node->ino)); | ||
488 | |||
489 | ref = kmalloc(sizeof(*ref), GFP_KERNEL); | ||
490 | if (!ref) | ||
491 | return -ENOMEM; | ||
492 | |||
493 | DJM(no_jffs_node_ref++); | ||
494 | ref->node = node; | ||
495 | ref->next = node->fm->nodes; | ||
496 | node->fm->nodes = ref; | ||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | |||
501 | /* Free a part of some allocated space. */ | ||
502 | void | ||
503 | jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, __u32 size) | ||
504 | { | ||
505 | D1(printk("***jffs_fmfree_partly(): fm = 0x%p, fm->nodes = 0x%p, " | ||
506 | "fm->nodes->node->ino = %u, size = %u\n", | ||
507 | fm, (fm ? fm->nodes : 0), | ||
508 | (!fm ? 0 : (!fm->nodes ? 0 : fm->nodes->node->ino)), size)); | ||
509 | |||
510 | if (fm->nodes) { | ||
511 | kfree(fm->nodes); | ||
512 | DJM(no_jffs_node_ref--); | ||
513 | fm->nodes = NULL; | ||
514 | } | ||
515 | fmc->used_size -= fm->size; | ||
516 | if (fm == fmc->tail) { | ||
517 | fm->size -= size; | ||
518 | fmc->free_size += size; | ||
519 | } | ||
520 | fmc->dirty_size += fm->size; | ||
521 | } | ||
522 | |||
523 | |||
524 | /* Find the jffs_fm struct that contains the end of the data chunk that | ||
525 | begins at the logical beginning of the flash memory and spans `size' | ||
526 | bytes. If we want to erase a sector of the flash memory, we use this | ||
527 | function to find where the sector limit cuts a chunk of data. */ | ||
528 | struct jffs_fm * | ||
529 | jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size) | ||
530 | { | ||
531 | struct jffs_fm *fm; | ||
532 | __u32 pos = 0; | ||
533 | |||
534 | if (size == 0) { | ||
535 | return NULL; | ||
536 | } | ||
537 | |||
538 | ASSERT(if (!fmc) { | ||
539 | printk(KERN_ERR "jffs_cut_node(): fmc == NULL\n"); | ||
540 | return NULL; | ||
541 | }); | ||
542 | |||
543 | fm = fmc->head; | ||
544 | |||
545 | while (fm) { | ||
546 | pos += fm->size; | ||
547 | if (pos < size) { | ||
548 | fm = fm->next; | ||
549 | } | ||
550 | else if (pos > size) { | ||
551 | break; | ||
552 | } | ||
553 | else { | ||
554 | fm = NULL; | ||
555 | break; | ||
556 | } | ||
557 | } | ||
558 | |||
559 | return fm; | ||
560 | } | ||
561 | |||
562 | |||
563 | /* Move the head of the fmc structures and delete the obsolete parts. */ | ||
564 | void | ||
565 | jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size) | ||
566 | { | ||
567 | struct jffs_fm *fm; | ||
568 | struct jffs_fm *del; | ||
569 | |||
570 | ASSERT(if (!fmc) { | ||
571 | printk(KERN_ERR "jffs_sync_erase(): fmc == NULL\n"); | ||
572 | return; | ||
573 | }); | ||
574 | |||
575 | fmc->dirty_size -= erased_size; | ||
576 | fmc->free_size += erased_size; | ||
577 | |||
578 | for (fm = fmc->head; fm && (erased_size > 0);) { | ||
579 | if (erased_size >= fm->size) { | ||
580 | erased_size -= fm->size; | ||
581 | del = fm; | ||
582 | fm = fm->next; | ||
583 | fm->prev = NULL; | ||
584 | fmc->head = fm; | ||
585 | jffs_free_fm(del); | ||
586 | } | ||
587 | else { | ||
588 | fm->size -= erased_size; | ||
589 | fm->offset += erased_size; | ||
590 | break; | ||
591 | } | ||
592 | } | ||
593 | } | ||
594 | |||
595 | |||
596 | /* Return the oldest used node in the flash memory. */ | ||
597 | struct jffs_node * | ||
598 | jffs_get_oldest_node(struct jffs_fmcontrol *fmc) | ||
599 | { | ||
600 | struct jffs_fm *fm; | ||
601 | struct jffs_node_ref *nref; | ||
602 | struct jffs_node *node = NULL; | ||
603 | |||
604 | ASSERT(if (!fmc) { | ||
605 | printk(KERN_ERR "jffs_get_oldest_node(): fmc == NULL\n"); | ||
606 | return NULL; | ||
607 | }); | ||
608 | |||
609 | for (fm = fmc->head; fm && !fm->nodes; fm = fm->next); | ||
610 | |||
611 | if (!fm) { | ||
612 | return NULL; | ||
613 | } | ||
614 | |||
615 | /* The oldest node is the last one in the reference list. This list | ||
616 | shouldn't be too long; just one or perhaps two elements. */ | ||
617 | for (nref = fm->nodes; nref; nref = nref->next) { | ||
618 | node = nref->node; | ||
619 | } | ||
620 | |||
621 | D2(printk("jffs_get_oldest_node(): ino = %u, version = %u\n", | ||
622 | (node ? node->ino : 0), (node ? node->version : 0))); | ||
623 | |||
624 | return node; | ||
625 | } | ||
626 | |||
627 | |||
628 | #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE | ||
629 | |||
630 | /* Mark an on-flash node as obsolete. | ||
631 | |||
632 | Note that this is just an optimization that isn't necessary for the | ||
633 | filesystem to work. */ | ||
634 | |||
635 | static int | ||
636 | jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset) | ||
637 | { | ||
638 | /* The `accurate_pos' holds the position of the accurate byte | ||
639 | in the jffs_raw_inode structure that we are going to mark | ||
640 | as obsolete. */ | ||
641 | __u32 accurate_pos = fm_offset + JFFS_RAW_INODE_ACCURATE_OFFSET; | ||
642 | unsigned char zero = 0x00; | ||
643 | size_t len; | ||
644 | |||
645 | D3(printk("jffs_mark_obsolete(): accurate_pos = %u\n", accurate_pos)); | ||
646 | ASSERT(if (!fmc) { | ||
647 | printk(KERN_ERR "jffs_mark_obsolete(): fmc == NULL\n"); | ||
648 | return -1; | ||
649 | }); | ||
650 | |||
651 | /* Write 0x00 to the raw inode's accurate member. Don't care | ||
652 | about the return value. */ | ||
653 | MTD_WRITE(fmc->mtd, accurate_pos, 1, &len, &zero); | ||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | #endif /* JFFS_MARK_OBSOLETE */ | ||
658 | |||
659 | /* check if it's possible to erase the wanted range, and if not, return | ||
660 | * the range that IS erasable, or a negative error code. | ||
661 | */ | ||
662 | static long | ||
663 | jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size) | ||
664 | { | ||
665 | u_long ssize; | ||
666 | |||
667 | /* assume that sector size for a partition is constant even | ||
668 | * if it spans more than one chip (you usually put the same | ||
669 | * type of chips in a system) | ||
670 | */ | ||
671 | |||
672 | ssize = mtd->erasesize; | ||
673 | |||
674 | if (offset % ssize) { | ||
675 | printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %x (erasesize %lx)\n", offset, ssize); | ||
676 | /* The offset is not sector size aligned. */ | ||
677 | return -1; | ||
678 | } | ||
679 | else if (offset > mtd->size) { | ||
680 | printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%x > %x)\n", offset, mtd->size); | ||
681 | return -2; | ||
682 | } | ||
683 | else if (offset + size > mtd->size) { | ||
684 | printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %x + len %x = %x, > %x)\n", offset,size, offset+size, mtd->size); | ||
685 | return -3; | ||
686 | } | ||
687 | |||
688 | return (size / ssize) * ssize; | ||
689 | } | ||
690 | |||
691 | |||
692 | /* How much dirty flash memory is possible to erase at the moment? */ | ||
693 | long | ||
694 | jffs_erasable_size(struct jffs_fmcontrol *fmc) | ||
695 | { | ||
696 | struct jffs_fm *fm; | ||
697 | __u32 size = 0; | ||
698 | long ret; | ||
699 | |||
700 | ASSERT(if (!fmc) { | ||
701 | printk(KERN_ERR "jffs_erasable_size(): fmc = NULL\n"); | ||
702 | return -1; | ||
703 | }); | ||
704 | |||
705 | if (!fmc->head) { | ||
706 | /* The flash memory is totally empty. No nodes. No dirt. | ||
707 | Just return. */ | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | /* Calculate how much space that is dirty. */ | ||
712 | for (fm = fmc->head; fm && !fm->nodes; fm = fm->next) { | ||
713 | if (size && fm->offset == 0) { | ||
714 | /* We have reached the beginning of the flash. */ | ||
715 | break; | ||
716 | } | ||
717 | size += fm->size; | ||
718 | } | ||
719 | |||
720 | /* Someone's signature contained this: | ||
721 | There's a fine line between fishing and just standing on | ||
722 | the shore like an idiot... */ | ||
723 | ret = jffs_flash_erasable_size(fmc->mtd, fmc->head->offset, size); | ||
724 | |||
725 | ASSERT(if (ret < 0) { | ||
726 | printk("jffs_erasable_size: flash_erasable_size() " | ||
727 | "returned something less than zero (%ld).\n", ret); | ||
728 | printk("jffs_erasable_size: offset = 0x%08x\n", | ||
729 | fmc->head->offset); | ||
730 | }); | ||
731 | |||
732 | /* If there is dirt on the flash (which is the reason to why | ||
733 | this function was called in the first place) but no space is | ||
734 | possible to erase right now, the initial part of the list of | ||
735 | jffs_fm structs, that hold place for dirty space, could perhaps | ||
736 | be shortened. The list's initial "dirty" elements are merged | ||
737 | into just one large dirty jffs_fm struct. This operation must | ||
738 | only be performed if nothing is possible to erase. Otherwise, | ||
739 | jffs_clear_end_of_node() won't work as expected. */ | ||
740 | if (ret == 0) { | ||
741 | struct jffs_fm *head = fmc->head; | ||
742 | struct jffs_fm *del; | ||
743 | /* While there are two dirty nodes beside each other.*/ | ||
744 | while (head->nodes == 0 | ||
745 | && head->next | ||
746 | && head->next->nodes == 0) { | ||
747 | del = head->next; | ||
748 | head->size += del->size; | ||
749 | head->next = del->next; | ||
750 | if (del->next) { | ||
751 | del->next->prev = head; | ||
752 | } | ||
753 | jffs_free_fm(del); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | return (ret >= 0 ? ret : 0); | ||
758 | } | ||
759 | |||
760 | static struct jffs_fm *jffs_alloc_fm(void) | ||
761 | { | ||
762 | struct jffs_fm *fm; | ||
763 | |||
764 | fm = kmem_cache_alloc(fm_cache,GFP_KERNEL); | ||
765 | DJM(if (fm) no_jffs_fm++;); | ||
766 | |||
767 | return fm; | ||
768 | } | ||
769 | |||
770 | static void jffs_free_fm(struct jffs_fm *n) | ||
771 | { | ||
772 | kmem_cache_free(fm_cache,n); | ||
773 | DJM(no_jffs_fm--); | ||
774 | } | ||
775 | |||
776 | |||
777 | |||
778 | struct jffs_node *jffs_alloc_node(void) | ||
779 | { | ||
780 | struct jffs_node *n; | ||
781 | |||
782 | n = (struct jffs_node *)kmem_cache_alloc(node_cache,GFP_KERNEL); | ||
783 | if(n != NULL) | ||
784 | no_jffs_node++; | ||
785 | return n; | ||
786 | } | ||
787 | |||
788 | void jffs_free_node(struct jffs_node *n) | ||
789 | { | ||
790 | kmem_cache_free(node_cache,n); | ||
791 | no_jffs_node--; | ||
792 | } | ||
793 | |||
794 | |||
795 | int jffs_get_node_inuse(void) | ||
796 | { | ||
797 | return no_jffs_node; | ||
798 | } | ||
diff --git a/fs/jffs/jffs_fm.h b/fs/jffs/jffs_fm.h deleted file mode 100644 index 9ee6ad29eff5..000000000000 --- a/fs/jffs/jffs_fm.h +++ /dev/null | |||
@@ -1,149 +0,0 @@ | |||
1 | /* | ||
2 | * JFFS -- Journaling Flash File System, Linux implementation. | ||
3 | * | ||
4 | * Copyright (C) 1999, 2000 Axis Communications AB. | ||
5 | * | ||
6 | * Created by Finn Hakansson <finn@axis.com>. | ||
7 | * | ||
8 | * This is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * $Id: jffs_fm.h,v 1.13 2001/01/11 12:03:25 dwmw2 Exp $ | ||
14 | * | ||
15 | * Ported to Linux 2.3.x and MTD: | ||
16 | * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #ifndef __LINUX_JFFS_FM_H__ | ||
21 | #define __LINUX_JFFS_FM_H__ | ||
22 | |||
23 | #include <linux/types.h> | ||
24 | #include <linux/jffs.h> | ||
25 | #include <linux/mtd/mtd.h> | ||
26 | #include <linux/mutex.h> | ||
27 | |||
28 | /* The alignment between two nodes in the flash memory. */ | ||
29 | #define JFFS_ALIGN_SIZE 4 | ||
30 | |||
31 | /* Mark the on-flash space as obsolete when appropriate. */ | ||
32 | #define JFFS_MARK_OBSOLETE 0 | ||
33 | |||
34 | #ifndef CONFIG_JFFS_FS_VERBOSE | ||
35 | #define CONFIG_JFFS_FS_VERBOSE 1 | ||
36 | #endif | ||
37 | |||
38 | #if CONFIG_JFFS_FS_VERBOSE > 0 | ||
39 | #define D(x) x | ||
40 | #define D1(x) D(x) | ||
41 | #else | ||
42 | #define D(x) | ||
43 | #define D1(x) | ||
44 | #endif | ||
45 | |||
46 | #if CONFIG_JFFS_FS_VERBOSE > 1 | ||
47 | #define D2(x) D(x) | ||
48 | #else | ||
49 | #define D2(x) | ||
50 | #endif | ||
51 | |||
52 | #if CONFIG_JFFS_FS_VERBOSE > 2 | ||
53 | #define D3(x) D(x) | ||
54 | #else | ||
55 | #define D3(x) | ||
56 | #endif | ||
57 | |||
58 | #define ASSERT(x) x | ||
59 | |||
60 | /* How many padding bytes should be inserted between two chunks of data | ||
61 | on the flash? */ | ||
62 | #define JFFS_GET_PAD_BYTES(size) ( (JFFS_ALIGN_SIZE-1) & -(__u32)(size) ) | ||
63 | #define JFFS_PAD(size) ( (size + (JFFS_ALIGN_SIZE-1)) & ~(JFFS_ALIGN_SIZE-1) ) | ||
64 | |||
65 | |||
66 | |||
67 | struct jffs_node_ref | ||
68 | { | ||
69 | struct jffs_node *node; | ||
70 | struct jffs_node_ref *next; | ||
71 | }; | ||
72 | |||
73 | |||
74 | /* The struct jffs_fm represents a chunk of data in the flash memory. */ | ||
75 | struct jffs_fm | ||
76 | { | ||
77 | __u32 offset; | ||
78 | __u32 size; | ||
79 | struct jffs_fm *prev; | ||
80 | struct jffs_fm *next; | ||
81 | struct jffs_node_ref *nodes; /* USED if != 0. */ | ||
82 | }; | ||
83 | |||
84 | struct jffs_fmcontrol | ||
85 | { | ||
86 | __u32 flash_size; | ||
87 | __u32 used_size; | ||
88 | __u32 dirty_size; | ||
89 | __u32 free_size; | ||
90 | __u32 sector_size; | ||
91 | __u32 min_free_size; /* The minimum free space needed to be able | ||
92 | to perform garbage collections. */ | ||
93 | __u32 max_chunk_size; /* The maximum size of a chunk of data. */ | ||
94 | struct mtd_info *mtd; | ||
95 | struct jffs_control *c; | ||
96 | struct jffs_fm *head; | ||
97 | struct jffs_fm *tail; | ||
98 | struct jffs_fm *head_extra; | ||
99 | struct jffs_fm *tail_extra; | ||
100 | struct mutex biglock; | ||
101 | }; | ||
102 | |||
103 | /* Notice the two members head_extra and tail_extra in the jffs_control | ||
104 | structure above. Those are only used during the scanning of the flash | ||
105 | memory; while the file system is being built. If the data in the flash | ||
106 | memory is organized like | ||
107 | |||
108 | +----------------+------------------+----------------+ | ||
109 | | USED / DIRTY | FREE | USED / DIRTY | | ||
110 | +----------------+------------------+----------------+ | ||
111 | |||
112 | then the scan is split in two parts. The first scanned part of the | ||
113 | flash memory is organized through the members head and tail. The | ||
114 | second scanned part is organized with head_extra and tail_extra. When | ||
115 | the scan is completed, the two lists are merged together. The jffs_fm | ||
116 | struct that head_extra references is the logical beginning of the | ||
117 | flash memory so it will be referenced by the head member. */ | ||
118 | |||
119 | |||
120 | |||
121 | struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, int unit); | ||
122 | void jffs_build_end(struct jffs_fmcontrol *fmc); | ||
123 | void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc); | ||
124 | |||
125 | int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, | ||
126 | struct jffs_node *node, struct jffs_fm **result); | ||
127 | int jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, | ||
128 | struct jffs_node *node); | ||
129 | |||
130 | __u32 jffs_free_size1(struct jffs_fmcontrol *fmc); | ||
131 | __u32 jffs_free_size2(struct jffs_fmcontrol *fmc); | ||
132 | void jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size); | ||
133 | struct jffs_fm *jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size); | ||
134 | struct jffs_node *jffs_get_oldest_node(struct jffs_fmcontrol *fmc); | ||
135 | long jffs_erasable_size(struct jffs_fmcontrol *fmc); | ||
136 | struct jffs_fm *jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, | ||
137 | __u32 size, struct jffs_node *node); | ||
138 | int jffs_add_node(struct jffs_node *node); | ||
139 | void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, | ||
140 | __u32 size); | ||
141 | |||
142 | #if CONFIG_JFFS_FS_VERBOSE > 0 | ||
143 | void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc); | ||
144 | #endif | ||
145 | #if 0 | ||
146 | void jffs_print_node_ref(struct jffs_node_ref *ref); | ||
147 | #endif /* 0 */ | ||
148 | |||
149 | #endif /* __LINUX_JFFS_FM_H__ */ | ||
diff --git a/fs/jffs/jffs_proc.c b/fs/jffs/jffs_proc.c deleted file mode 100644 index 9bdd99a557c2..000000000000 --- a/fs/jffs/jffs_proc.c +++ /dev/null | |||
@@ -1,261 +0,0 @@ | |||
1 | /* | ||
2 | * JFFS -- Journaling Flash File System, Linux implementation. | ||
3 | * | ||
4 | * Copyright (C) 2000 Axis Communications AB. | ||
5 | * | ||
6 | * Created by Simon Kagstrom <simonk@axis.com>. | ||
7 | * | ||
8 | * $Id: jffs_proc.c,v 1.5 2001/06/02 14:34:55 dwmw2 Exp $ | ||
9 | * | ||
10 | * This is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * Overview: | ||
16 | * This file defines JFFS partition entries in the proc file system. | ||
17 | * | ||
18 | * TODO: | ||
19 | * Create some more proc files for different kinds of info, i.e. statistics | ||
20 | * about written and read bytes, number of calls to different routines, | ||
21 | * reports about failures. | ||
22 | */ | ||
23 | |||
24 | #include <linux/errno.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/jffs.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/proc_fs.h> | ||
29 | #include <linux/time.h> | ||
30 | #include <linux/types.h> | ||
31 | #include "jffs_fm.h" | ||
32 | #include "jffs_proc.h" | ||
33 | |||
34 | /* | ||
35 | * Structure for a JFFS partition in the system | ||
36 | */ | ||
37 | struct jffs_partition_dir { | ||
38 | struct jffs_control *c; | ||
39 | struct proc_dir_entry *part_root; | ||
40 | struct proc_dir_entry *part_info; | ||
41 | struct proc_dir_entry *part_layout; | ||
42 | struct jffs_partition_dir *next; | ||
43 | }; | ||
44 | |||
45 | /* | ||
46 | * Structure for top-level entry in '/proc/fs' directory | ||
47 | */ | ||
48 | struct proc_dir_entry *jffs_proc_root; | ||
49 | |||
50 | /* | ||
51 | * Linked list of 'jffs_partition_dirs' to help us track | ||
52 | * the mounted JFFS partitions in the system | ||
53 | */ | ||
54 | static struct jffs_partition_dir *jffs_part_dirs; | ||
55 | |||
56 | /* | ||
57 | * Read functions for entries | ||
58 | */ | ||
59 | static int jffs_proc_info_read(char *page, char **start, off_t off, | ||
60 | int count, int *eof, void *data); | ||
61 | static int jffs_proc_layout_read (char *page, char **start, off_t off, | ||
62 | int count, int *eof, void *data); | ||
63 | |||
64 | |||
65 | /* | ||
66 | * Register a JFFS partition directory (called upon mount) | ||
67 | */ | ||
68 | int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c) | ||
69 | { | ||
70 | struct jffs_partition_dir *part_dir; | ||
71 | struct proc_dir_entry *part_info = NULL; | ||
72 | struct proc_dir_entry *part_layout = NULL; | ||
73 | struct proc_dir_entry *part_root = NULL; | ||
74 | char name[10]; | ||
75 | |||
76 | sprintf(name, "%d", mtd); | ||
77 | /* Allocate structure for local JFFS partition table */ | ||
78 | part_dir = (struct jffs_partition_dir *) | ||
79 | kmalloc(sizeof (struct jffs_partition_dir), GFP_KERNEL); | ||
80 | if (!part_dir) | ||
81 | goto out; | ||
82 | |||
83 | /* Create entry for this partition */ | ||
84 | part_root = proc_mkdir(name, jffs_proc_root); | ||
85 | if (!part_root) | ||
86 | goto out1; | ||
87 | |||
88 | /* Create entry for 'info' file */ | ||
89 | part_info = create_proc_entry ("info", 0, part_root); | ||
90 | if (!part_info) | ||
91 | goto out2; | ||
92 | part_info->read_proc = jffs_proc_info_read; | ||
93 | part_info->data = (void *) c; | ||
94 | |||
95 | /* Create entry for 'layout' file */ | ||
96 | part_layout = create_proc_entry ("layout", 0, part_root); | ||
97 | if (!part_layout) | ||
98 | goto out3; | ||
99 | part_layout->read_proc = jffs_proc_layout_read; | ||
100 | part_layout->data = (void *) c; | ||
101 | |||
102 | /* Fill in structure for table and insert in the list */ | ||
103 | part_dir->c = c; | ||
104 | part_dir->part_root = part_root; | ||
105 | part_dir->part_info = part_info; | ||
106 | part_dir->part_layout = part_layout; | ||
107 | part_dir->next = jffs_part_dirs; | ||
108 | jffs_part_dirs = part_dir; | ||
109 | |||
110 | /* Return happy */ | ||
111 | return 0; | ||
112 | |||
113 | out3: | ||
114 | remove_proc_entry("info", part_root); | ||
115 | out2: | ||
116 | remove_proc_entry(name, jffs_proc_root); | ||
117 | out1: | ||
118 | kfree(part_dir); | ||
119 | out: | ||
120 | return -ENOMEM; | ||
121 | } | ||
122 | |||
123 | |||
124 | /* | ||
125 | * Unregister a JFFS partition directory (called at umount) | ||
126 | */ | ||
127 | int jffs_unregister_jffs_proc_dir(struct jffs_control *c) | ||
128 | { | ||
129 | struct jffs_partition_dir *part_dir = jffs_part_dirs; | ||
130 | struct jffs_partition_dir *prev_part_dir = NULL; | ||
131 | |||
132 | while (part_dir) { | ||
133 | if (part_dir->c == c) { | ||
134 | /* Remove entries for partition */ | ||
135 | remove_proc_entry (part_dir->part_info->name, | ||
136 | part_dir->part_root); | ||
137 | remove_proc_entry (part_dir->part_layout->name, | ||
138 | part_dir->part_root); | ||
139 | remove_proc_entry (part_dir->part_root->name, | ||
140 | jffs_proc_root); | ||
141 | |||
142 | /* Remove entry from list */ | ||
143 | if (prev_part_dir) | ||
144 | prev_part_dir->next = part_dir->next; | ||
145 | else | ||
146 | jffs_part_dirs = part_dir->next; | ||
147 | |||
148 | /* | ||
149 | * Check to see if this is the last one | ||
150 | * and remove the entry from '/proc/fs' | ||
151 | * if it is. | ||
152 | */ | ||
153 | if (jffs_part_dirs == part_dir->next) | ||
154 | remove_proc_entry ("jffs", proc_root_fs); | ||
155 | |||
156 | /* Free memory for entry */ | ||
157 | kfree(part_dir); | ||
158 | |||
159 | /* Return happy */ | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | /* Move to next entry */ | ||
164 | prev_part_dir = part_dir; | ||
165 | part_dir = part_dir->next; | ||
166 | } | ||
167 | |||
168 | /* Return unhappy */ | ||
169 | return -1; | ||
170 | } | ||
171 | |||
172 | |||
173 | /* | ||
174 | * Read a JFFS partition's `info' file | ||
175 | */ | ||
176 | static int jffs_proc_info_read (char *page, char **start, off_t off, | ||
177 | int count, int *eof, void *data) | ||
178 | { | ||
179 | struct jffs_control *c = (struct jffs_control *) data; | ||
180 | int len = 0; | ||
181 | |||
182 | /* Get information on the parition */ | ||
183 | len += sprintf (page, | ||
184 | "partition size: %08lX (%u)\n" | ||
185 | "sector size: %08lX (%u)\n" | ||
186 | "used size: %08lX (%u)\n" | ||
187 | "dirty size: %08lX (%u)\n" | ||
188 | "free size: %08lX (%u)\n\n", | ||
189 | (unsigned long) c->fmc->flash_size, c->fmc->flash_size, | ||
190 | (unsigned long) c->fmc->sector_size, c->fmc->sector_size, | ||
191 | (unsigned long) c->fmc->used_size, c->fmc->used_size, | ||
192 | (unsigned long) c->fmc->dirty_size, c->fmc->dirty_size, | ||
193 | (unsigned long) (c->fmc->flash_size - | ||
194 | (c->fmc->used_size + c->fmc->dirty_size)), | ||
195 | c->fmc->flash_size - (c->fmc->used_size + c->fmc->dirty_size)); | ||
196 | |||
197 | /* We're done */ | ||
198 | *eof = 1; | ||
199 | |||
200 | /* Return length */ | ||
201 | return len; | ||
202 | } | ||
203 | |||
204 | |||
205 | /* | ||
206 | * Read a JFFS partition's `layout' file | ||
207 | */ | ||
208 | static int jffs_proc_layout_read (char *page, char **start, off_t off, | ||
209 | int count, int *eof, void *data) | ||
210 | { | ||
211 | struct jffs_control *c = (struct jffs_control *) data; | ||
212 | struct jffs_fm *fm = NULL; | ||
213 | struct jffs_fm *last_fm = NULL; | ||
214 | int len = 0; | ||
215 | |||
216 | /* Get the first item in the list */ | ||
217 | fm = c->fmc->head; | ||
218 | |||
219 | /* Print free space */ | ||
220 | if (fm && fm->offset) { | ||
221 | len += sprintf (page, "00000000 %08lX free\n", | ||
222 | (unsigned long) fm->offset); | ||
223 | } | ||
224 | |||
225 | /* Loop through all of the flash control structures */ | ||
226 | while (fm && (len < (off + count))) { | ||
227 | if (fm->nodes) { | ||
228 | len += sprintf (page + len, | ||
229 | "%08lX %08lX ino=%08lX, ver=%08lX\n", | ||
230 | (unsigned long) fm->offset, | ||
231 | (unsigned long) fm->size, | ||
232 | (unsigned long) fm->nodes->node->ino, | ||
233 | (unsigned long) fm->nodes->node->version); | ||
234 | } | ||
235 | else { | ||
236 | len += sprintf (page + len, | ||
237 | "%08lX %08lX dirty\n", | ||
238 | (unsigned long) fm->offset, | ||
239 | (unsigned long) fm->size); | ||
240 | } | ||
241 | last_fm = fm; | ||
242 | fm = fm->next; | ||
243 | } | ||
244 | |||
245 | /* Print free space */ | ||
246 | if ((len < (off + count)) && last_fm | ||
247 | && (last_fm->offset < c->fmc->flash_size)) { | ||
248 | len += sprintf (page + len, | ||
249 | "%08lX %08lX free\n", | ||
250 | (unsigned long) last_fm->offset + | ||
251 | last_fm->size, | ||
252 | (unsigned long) (c->fmc->flash_size - | ||
253 | (last_fm->offset + last_fm->size))); | ||
254 | } | ||
255 | |||
256 | /* We're done */ | ||
257 | *eof = 1; | ||
258 | |||
259 | /* Return length */ | ||
260 | return len; | ||
261 | } | ||
diff --git a/fs/jffs/jffs_proc.h b/fs/jffs/jffs_proc.h deleted file mode 100644 index 39a1c5d162b0..000000000000 --- a/fs/jffs/jffs_proc.h +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* | ||
2 | * JFFS -- Journaling Flash File System, Linux implementation. | ||
3 | * | ||
4 | * Copyright (C) 2000 Axis Communications AB. | ||
5 | * | ||
6 | * Created by Simon Kagstrom <simonk@axis.com>. | ||
7 | * | ||
8 | * This is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * $Id: jffs_proc.h,v 1.2 2000/11/15 22:04:12 sjhill Exp $ | ||
14 | */ | ||
15 | |||
16 | /* jffs_proc.h defines a structure for inclusion in the proc-file system. */ | ||
17 | #ifndef __LINUX_JFFS_PROC_H__ | ||
18 | #define __LINUX_JFFS_PROC_H__ | ||
19 | |||
20 | #include <linux/proc_fs.h> | ||
21 | |||
22 | /* The proc_dir_entry for jffs (defined in jffs_proc.c). */ | ||
23 | extern struct proc_dir_entry *jffs_proc_root; | ||
24 | |||
25 | int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c); | ||
26 | int jffs_unregister_jffs_proc_dir(struct jffs_control *c); | ||
27 | |||
28 | #endif /* __LINUX_JFFS_PROC_H__ */ | ||
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 02826967ab58..07119c42a861 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c | |||
@@ -348,23 +348,27 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) | |||
348 | 348 | ||
349 | ret = jffs2_sum_init(c); | 349 | ret = jffs2_sum_init(c); |
350 | if (ret) | 350 | if (ret) |
351 | return ret; | 351 | goto out_free; |
352 | 352 | ||
353 | if (jffs2_build_filesystem(c)) { | 353 | if (jffs2_build_filesystem(c)) { |
354 | dbg_fsbuild("build_fs failed\n"); | 354 | dbg_fsbuild("build_fs failed\n"); |
355 | jffs2_free_ino_caches(c); | 355 | jffs2_free_ino_caches(c); |
356 | jffs2_free_raw_node_refs(c); | 356 | jffs2_free_raw_node_refs(c); |
357 | #ifndef __ECOS | 357 | ret = -EIO; |
358 | if (jffs2_blocks_use_vmalloc(c)) | 358 | goto out_free; |
359 | vfree(c->blocks); | ||
360 | else | ||
361 | #endif | ||
362 | kfree(c->blocks); | ||
363 | |||
364 | return -EIO; | ||
365 | } | 359 | } |
366 | 360 | ||
367 | jffs2_calc_trigger_levels(c); | 361 | jffs2_calc_trigger_levels(c); |
368 | 362 | ||
369 | return 0; | 363 | return 0; |
364 | |||
365 | out_free: | ||
366 | #ifndef __ECOS | ||
367 | if (jffs2_blocks_use_vmalloc(c)) | ||
368 | vfree(c->blocks); | ||
369 | else | ||
370 | #endif | ||
371 | kfree(c->blocks); | ||
372 | |||
373 | return ret; | ||
370 | } | 374 | } |
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 3681d0728ac7..0c1fc6e20b43 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #endif | 16 | #endif |
17 | 17 | ||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/sched.h> | ||
20 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
21 | #include <linux/zlib.h> | 20 | #include <linux/zlib.h> |
22 | #include <linux/zutil.h> | 21 | #include <linux/zutil.h> |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index da6034d50718..9fa2e27f0641 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/sched.h> | ||
17 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
18 | #include <linux/crc32.h> | 17 | #include <linux/crc32.h> |
19 | #include <linux/jffs2.h> | 18 | #include <linux/jffs2.h> |
@@ -46,7 +45,7 @@ const struct file_operations jffs2_dir_operations = | |||
46 | }; | 45 | }; |
47 | 46 | ||
48 | 47 | ||
49 | struct inode_operations jffs2_dir_inode_operations = | 48 | const struct inode_operations jffs2_dir_inode_operations = |
50 | { | 49 | { |
51 | .create = jffs2_create, | 50 | .create = jffs2_create, |
52 | .lookup = jffs2_lookup, | 51 | .lookup = jffs2_lookup, |
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 242875f77cb3..e82eeaf7590d 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c | |||
@@ -54,7 +54,7 @@ const struct file_operations jffs2_file_operations = | |||
54 | 54 | ||
55 | /* jffs2_file_inode_operations */ | 55 | /* jffs2_file_inode_operations */ |
56 | 56 | ||
57 | struct inode_operations jffs2_file_inode_operations = | 57 | const struct inode_operations jffs2_file_inode_operations = |
58 | { | 58 | { |
59 | .permission = jffs2_permission, | 59 | .permission = jffs2_permission, |
60 | .setattr = jffs2_setattr, | 60 | .setattr = jffs2_setattr, |
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index b98594992eed..ea88f69af130 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
@@ -98,20 +98,14 @@ struct jffs2_sb_info { | |||
98 | uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ | 98 | uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ |
99 | 99 | ||
100 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | 100 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER |
101 | /* Write-behind buffer for NAND flash */ | 101 | unsigned char *wbuf; /* Write-behind buffer for NAND flash */ |
102 | unsigned char *wbuf; | ||
103 | unsigned char *oobbuf; | ||
104 | uint32_t wbuf_ofs; | 102 | uint32_t wbuf_ofs; |
105 | uint32_t wbuf_len; | 103 | uint32_t wbuf_len; |
106 | struct jffs2_inodirty *wbuf_inodes; | 104 | struct jffs2_inodirty *wbuf_inodes; |
107 | |||
108 | struct rw_semaphore wbuf_sem; /* Protects the write buffer */ | 105 | struct rw_semaphore wbuf_sem; /* Protects the write buffer */ |
109 | 106 | ||
110 | /* Information about out-of-band area usage... */ | 107 | unsigned char *oobbuf; |
111 | struct nand_ecclayout *ecclayout; | 108 | int oobavail; /* How many bytes are available for JFFS2 in OOB */ |
112 | uint32_t badblock_pos; | ||
113 | uint32_t fsdata_pos; | ||
114 | uint32_t fsdata_len; | ||
115 | #endif | 109 | #endif |
116 | 110 | ||
117 | struct jffs2_summary *summary; /* Summary information */ | 111 | struct jffs2_summary *summary; /* Summary information */ |
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 9f41fc01a371..e07a0edcdb4f 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
@@ -153,11 +153,11 @@ void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); | |||
153 | 153 | ||
154 | /* dir.c */ | 154 | /* dir.c */ |
155 | extern const struct file_operations jffs2_dir_operations; | 155 | extern const struct file_operations jffs2_dir_operations; |
156 | extern struct inode_operations jffs2_dir_inode_operations; | 156 | extern const struct inode_operations jffs2_dir_inode_operations; |
157 | 157 | ||
158 | /* file.c */ | 158 | /* file.c */ |
159 | extern const struct file_operations jffs2_file_operations; | 159 | extern const struct file_operations jffs2_file_operations; |
160 | extern struct inode_operations jffs2_file_inode_operations; | 160 | extern const struct inode_operations jffs2_file_inode_operations; |
161 | extern const struct address_space_operations jffs2_file_address_operations; | 161 | extern const struct address_space_operations jffs2_file_address_operations; |
162 | int jffs2_fsync(struct file *, struct dentry *, int); | 162 | int jffs2_fsync(struct file *, struct dentry *, int); |
163 | int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); | 163 | int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); |
@@ -166,7 +166,7 @@ int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); | |||
166 | int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long); | 166 | int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long); |
167 | 167 | ||
168 | /* symlink.c */ | 168 | /* symlink.c */ |
169 | extern struct inode_operations jffs2_symlink_inode_operations; | 169 | extern const struct inode_operations jffs2_symlink_inode_operations; |
170 | 170 | ||
171 | /* fs.c */ | 171 | /* fs.c */ |
172 | int jffs2_setattr (struct dentry *, struct iattr *); | 172 | int jffs2_setattr (struct dentry *, struct iattr *); |
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 3af746eaff0e..31c1475d922a 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -450,16 +450,20 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
450 | 450 | ||
451 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | 451 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER |
452 | if (jffs2_cleanmarker_oob(c)) { | 452 | if (jffs2_cleanmarker_oob(c)) { |
453 | int ret = jffs2_check_nand_cleanmarker(c, jeb); | 453 | int ret; |
454 | |||
455 | if (c->mtd->block_isbad(c->mtd, jeb->offset)) | ||
456 | return BLK_STATE_BADBLOCK; | ||
457 | |||
458 | ret = jffs2_check_nand_cleanmarker(c, jeb); | ||
454 | D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret)); | 459 | D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret)); |
460 | |||
455 | /* Even if it's not found, we still scan to see | 461 | /* Even if it's not found, we still scan to see |
456 | if the block is empty. We use this information | 462 | if the block is empty. We use this information |
457 | to decide whether to erase it or not. */ | 463 | to decide whether to erase it or not. */ |
458 | switch (ret) { | 464 | switch (ret) { |
459 | case 0: cleanmarkerfound = 1; break; | 465 | case 0: cleanmarkerfound = 1; break; |
460 | case 1: break; | 466 | case 1: break; |
461 | case 2: return BLK_STATE_BADBLOCK; | ||
462 | case 3: return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */ | ||
463 | default: return ret; | 467 | default: return ret; |
464 | } | 468 | } |
465 | } | 469 | } |
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 25265965bdc1..30f888414ce7 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c | |||
@@ -14,7 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/sched.h> | ||
18 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
19 | #include <linux/mtd/mtd.h> | 18 | #include <linux/mtd/mtd.h> |
20 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 08a0e6c49e61..cc7e8e71ad46 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
@@ -66,7 +66,7 @@ static int jffs2_sync_fs(struct super_block *sb, int wait) | |||
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
68 | 68 | ||
69 | static struct super_operations jffs2_super_operations = | 69 | static const struct super_operations jffs2_super_operations = |
70 | { | 70 | { |
71 | .alloc_inode = jffs2_alloc_inode, | 71 | .alloc_inode = jffs2_alloc_inode, |
72 | .destroy_inode =jffs2_destroy_inode, | 72 | .destroy_inode =jffs2_destroy_inode, |
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index b90d5aa3d969..7e4882c8a7ed 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); | 21 | static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); |
22 | 22 | ||
23 | struct inode_operations jffs2_symlink_inode_operations = | 23 | const struct inode_operations jffs2_symlink_inode_operations = |
24 | { | 24 | { |
25 | .readlink = generic_readlink, | 25 | .readlink = generic_readlink, |
26 | .follow_link = jffs2_follow_link, | 26 | .follow_link = jffs2_follow_link, |
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 9c99859f5edd..de718e3a1692 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
@@ -957,43 +957,48 @@ exit: | |||
957 | return ret; | 957 | return ret; |
958 | } | 958 | } |
959 | 959 | ||
960 | #define NR_OOB_SCAN_PAGES 4 | 960 | #define NR_OOB_SCAN_PAGES 4 |
961 | |||
962 | /* For historical reasons we use only 12 bytes for OOB clean marker */ | ||
963 | #define OOB_CM_SIZE 12 | ||
964 | |||
965 | static const struct jffs2_unknown_node oob_cleanmarker = | ||
966 | { | ||
967 | .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), | ||
968 | .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), | ||
969 | .totlen = cpu_to_je32(8) | ||
970 | }; | ||
961 | 971 | ||
962 | /* | 972 | /* |
963 | * Check, if the out of band area is empty | 973 | * Check, if the out of band area is empty. This function knows about the clean |
974 | * marker and if it is present in OOB, treats the OOB as empty anyway. | ||
964 | */ | 975 | */ |
965 | int jffs2_check_oob_empty(struct jffs2_sb_info *c, | 976 | int jffs2_check_oob_empty(struct jffs2_sb_info *c, |
966 | struct jffs2_eraseblock *jeb, int mode) | 977 | struct jffs2_eraseblock *jeb, int mode) |
967 | { | 978 | { |
968 | int i, page, ret; | 979 | int i, ret; |
969 | int oobsize = c->mtd->oobsize; | 980 | int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); |
970 | struct mtd_oob_ops ops; | 981 | struct mtd_oob_ops ops; |
971 | 982 | ||
972 | ops.ooblen = NR_OOB_SCAN_PAGES * oobsize; | 983 | ops.mode = MTD_OOB_AUTO; |
984 | ops.ooblen = NR_OOB_SCAN_PAGES * c->oobavail; | ||
973 | ops.oobbuf = c->oobbuf; | 985 | ops.oobbuf = c->oobbuf; |
974 | ops.ooboffs = 0; | 986 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; |
975 | ops.datbuf = NULL; | 987 | ops.datbuf = NULL; |
976 | ops.mode = MTD_OOB_PLACE; | ||
977 | 988 | ||
978 | ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops); | 989 | ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops); |
979 | if (ret) { | 990 | if (ret || ops.oobretlen != ops.ooblen) { |
980 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB " | 991 | printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd" |
981 | "failed %d for block at %08x\n", ret, jeb->offset)); | 992 | " bytes, read %zd bytes, error %d\n", |
993 | jeb->offset, ops.ooblen, ops.oobretlen, ret); | ||
994 | if (!ret) | ||
995 | ret = -EIO; | ||
982 | return ret; | 996 | return ret; |
983 | } | 997 | } |
984 | 998 | ||
985 | if (ops.oobretlen < ops.ooblen) { | 999 | for(i = 0; i < ops.ooblen; i++) { |
986 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB " | 1000 | if (mode && i < cmlen) |
987 | "returned short read (%zd bytes not %d) for block " | 1001 | /* Yeah, we know about the cleanmarker */ |
988 | "at %08x\n", ops.oobretlen, ops.ooblen, jeb->offset)); | ||
989 | return -EIO; | ||
990 | } | ||
991 | |||
992 | /* Special check for first page */ | ||
993 | for(i = 0; i < oobsize ; i++) { | ||
994 | /* Yeah, we know about the cleanmarker. */ | ||
995 | if (mode && i >= c->fsdata_pos && | ||
996 | i < c->fsdata_pos + c->fsdata_len) | ||
997 | continue; | 1002 | continue; |
998 | 1003 | ||
999 | if (ops.oobbuf[i] != 0xFF) { | 1004 | if (ops.oobbuf[i] != 0xFF) { |
@@ -1003,111 +1008,63 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, | |||
1003 | } | 1008 | } |
1004 | } | 1009 | } |
1005 | 1010 | ||
1006 | /* we know, we are aligned :) */ | ||
1007 | for (page = oobsize; page < ops.ooblen; page += sizeof(long)) { | ||
1008 | long dat = *(long *)(&ops.oobbuf[page]); | ||
1009 | if(dat != -1) | ||
1010 | return 1; | ||
1011 | } | ||
1012 | return 0; | 1011 | return 0; |
1013 | } | 1012 | } |
1014 | 1013 | ||
1015 | /* | 1014 | /* |
1016 | * Scan for a valid cleanmarker and for bad blocks | 1015 | * Check for a valid cleanmarker. |
1016 | * Returns: 0 if a valid cleanmarker was found | ||
1017 | * 1 if no cleanmarker was found | ||
1018 | * negative error code if an error occurred | ||
1017 | */ | 1019 | */ |
1018 | int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, | 1020 | int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, |
1019 | struct jffs2_eraseblock *jeb) | 1021 | struct jffs2_eraseblock *jeb) |
1020 | { | 1022 | { |
1021 | struct jffs2_unknown_node n; | ||
1022 | struct mtd_oob_ops ops; | 1023 | struct mtd_oob_ops ops; |
1023 | int oobsize = c->mtd->oobsize; | 1024 | int ret, cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); |
1024 | unsigned char *p,*b; | ||
1025 | int i, ret; | ||
1026 | size_t offset = jeb->offset; | ||
1027 | |||
1028 | /* Check first if the block is bad. */ | ||
1029 | if (c->mtd->block_isbad(c->mtd, offset)) { | ||
1030 | D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker()" | ||
1031 | ": Bad block at %08x\n", jeb->offset)); | ||
1032 | return 2; | ||
1033 | } | ||
1034 | 1025 | ||
1035 | ops.ooblen = oobsize; | 1026 | ops.mode = MTD_OOB_AUTO; |
1027 | ops.ooblen = cmlen; | ||
1036 | ops.oobbuf = c->oobbuf; | 1028 | ops.oobbuf = c->oobbuf; |
1037 | ops.ooboffs = 0; | 1029 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; |
1038 | ops.datbuf = NULL; | 1030 | ops.datbuf = NULL; |
1039 | ops.mode = MTD_OOB_PLACE; | ||
1040 | 1031 | ||
1041 | ret = c->mtd->read_oob(c->mtd, offset, &ops); | 1032 | ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops); |
1042 | if (ret) { | 1033 | if (ret || ops.oobretlen != ops.ooblen) { |
1043 | D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): " | 1034 | printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd" |
1044 | "Read OOB failed %d for block at %08x\n", | 1035 | " bytes, read %zd bytes, error %d\n", |
1045 | ret, jeb->offset)); | 1036 | jeb->offset, ops.ooblen, ops.oobretlen, ret); |
1037 | if (!ret) | ||
1038 | ret = -EIO; | ||
1046 | return ret; | 1039 | return ret; |
1047 | } | 1040 | } |
1048 | 1041 | ||
1049 | if (ops.oobretlen < ops.ooblen) { | 1042 | return !!memcmp(&oob_cleanmarker, c->oobbuf, cmlen); |
1050 | D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): " | ||
1051 | "Read OOB return short read (%zd bytes not %d) " | ||
1052 | "for block at %08x\n", ops.oobretlen, ops.ooblen, | ||
1053 | jeb->offset)); | ||
1054 | return -EIO; | ||
1055 | } | ||
1056 | |||
1057 | n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK); | ||
1058 | n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER); | ||
1059 | n.totlen = cpu_to_je32 (8); | ||
1060 | p = (unsigned char *) &n; | ||
1061 | b = c->oobbuf + c->fsdata_pos; | ||
1062 | |||
1063 | for (i = c->fsdata_len; i; i--) { | ||
1064 | if (*b++ != *p++) | ||
1065 | ret = 1; | ||
1066 | } | ||
1067 | |||
1068 | D1(if (ret == 1) { | ||
1069 | printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): " | ||
1070 | "Cleanmarker node not detected in block at %08x\n", | ||
1071 | offset); | ||
1072 | printk(KERN_WARNING "OOB at %08zx was ", offset); | ||
1073 | for (i=0; i < oobsize; i++) | ||
1074 | printk("%02x ", c->oobbuf[i]); | ||
1075 | printk("\n"); | ||
1076 | }); | ||
1077 | return ret; | ||
1078 | } | 1043 | } |
1079 | 1044 | ||
1080 | int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, | 1045 | int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, |
1081 | struct jffs2_eraseblock *jeb) | 1046 | struct jffs2_eraseblock *jeb) |
1082 | { | 1047 | { |
1083 | struct jffs2_unknown_node n; | 1048 | int ret; |
1084 | int ret; | ||
1085 | struct mtd_oob_ops ops; | 1049 | struct mtd_oob_ops ops; |
1050 | int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); | ||
1086 | 1051 | ||
1087 | n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 1052 | ops.mode = MTD_OOB_AUTO; |
1088 | n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); | 1053 | ops.ooblen = cmlen; |
1089 | n.totlen = cpu_to_je32(8); | 1054 | ops.oobbuf = (uint8_t *)&oob_cleanmarker; |
1090 | 1055 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; | |
1091 | ops.ooblen = c->fsdata_len; | ||
1092 | ops.oobbuf = (uint8_t *)&n; | ||
1093 | ops.ooboffs = c->fsdata_pos; | ||
1094 | ops.datbuf = NULL; | 1056 | ops.datbuf = NULL; |
1095 | ops.mode = MTD_OOB_PLACE; | ||
1096 | 1057 | ||
1097 | ret = c->mtd->write_oob(c->mtd, jeb->offset, &ops); | 1058 | ret = c->mtd->write_oob(c->mtd, jeb->offset, &ops); |
1098 | 1059 | if (ret || ops.oobretlen != ops.ooblen) { | |
1099 | if (ret) { | 1060 | printk(KERN_ERR "cannot write OOB for EB at %08x, requested %zd" |
1100 | D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): " | 1061 | " bytes, read %zd bytes, error %d\n", |
1101 | "Write failed for block at %08x: error %d\n", | 1062 | jeb->offset, ops.ooblen, ops.oobretlen, ret); |
1102 | jeb->offset, ret)); | 1063 | if (!ret) |
1064 | ret = -EIO; | ||
1103 | return ret; | 1065 | return ret; |
1104 | } | 1066 | } |
1105 | if (ops.oobretlen != ops.ooblen) { | 1067 | |
1106 | D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): " | ||
1107 | "Short write for block at %08x: %zd not %d\n", | ||
1108 | jeb->offset, ops.oobretlen, ops.ooblen)); | ||
1109 | return -EIO; | ||
1110 | } | ||
1111 | return 0; | 1068 | return 0; |
1112 | } | 1069 | } |
1113 | 1070 | ||
@@ -1140,41 +1097,24 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock * | |||
1140 | return 1; | 1097 | return 1; |
1141 | } | 1098 | } |
1142 | 1099 | ||
1143 | static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) | 1100 | int jffs2_nand_flash_setup(struct jffs2_sb_info *c) |
1144 | { | 1101 | { |
1145 | struct nand_ecclayout *oinfo = c->mtd->ecclayout; | 1102 | struct nand_ecclayout *oinfo = c->mtd->ecclayout; |
1146 | 1103 | ||
1147 | /* Do this only, if we have an oob buffer */ | ||
1148 | if (!c->mtd->oobsize) | 1104 | if (!c->mtd->oobsize) |
1149 | return 0; | 1105 | return 0; |
1150 | 1106 | ||
1151 | /* Cleanmarker is out-of-band, so inline size zero */ | 1107 | /* Cleanmarker is out-of-band, so inline size zero */ |
1152 | c->cleanmarker_size = 0; | 1108 | c->cleanmarker_size = 0; |
1153 | 1109 | ||
1154 | /* Should we use autoplacement ? */ | 1110 | if (!oinfo || oinfo->oobavail == 0) { |
1155 | if (!oinfo) { | 1111 | printk(KERN_ERR "inconsistent device description\n"); |
1156 | D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n")); | ||
1157 | return -EINVAL; | 1112 | return -EINVAL; |
1158 | } | 1113 | } |
1159 | 1114 | ||
1160 | D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n")); | 1115 | D1(printk(KERN_DEBUG "JFFS2 using OOB on NAND\n")); |
1161 | /* Get the position of the free bytes */ | ||
1162 | if (!oinfo->oobfree[0].length) { | ||
1163 | printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep." | ||
1164 | " Autoplacement selected and no empty space in oob\n"); | ||
1165 | return -ENOSPC; | ||
1166 | } | ||
1167 | c->fsdata_pos = oinfo->oobfree[0].offset; | ||
1168 | c->fsdata_len = oinfo->oobfree[0].length; | ||
1169 | if (c->fsdata_len > 8) | ||
1170 | c->fsdata_len = 8; | ||
1171 | 1116 | ||
1172 | return 0; | 1117 | c->oobavail = oinfo->oobavail; |
1173 | } | ||
1174 | |||
1175 | int jffs2_nand_flash_setup(struct jffs2_sb_info *c) | ||
1176 | { | ||
1177 | int res; | ||
1178 | 1118 | ||
1179 | /* Initialise write buffer */ | 1119 | /* Initialise write buffer */ |
1180 | init_rwsem(&c->wbuf_sem); | 1120 | init_rwsem(&c->wbuf_sem); |
@@ -1185,22 +1125,13 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) | |||
1185 | if (!c->wbuf) | 1125 | if (!c->wbuf) |
1186 | return -ENOMEM; | 1126 | return -ENOMEM; |
1187 | 1127 | ||
1188 | c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->mtd->oobsize, GFP_KERNEL); | 1128 | c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->oobavail, GFP_KERNEL); |
1189 | if (!c->oobbuf) | 1129 | if (!c->oobbuf) { |
1190 | return -ENOMEM; | ||
1191 | |||
1192 | res = jffs2_nand_set_oobinfo(c); | ||
1193 | |||
1194 | #ifdef BREAKME | ||
1195 | if (!brokenbuf) | ||
1196 | brokenbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | ||
1197 | if (!brokenbuf) { | ||
1198 | kfree(c->wbuf); | 1130 | kfree(c->wbuf); |
1199 | return -ENOMEM; | 1131 | return -ENOMEM; |
1200 | } | 1132 | } |
1201 | memset(brokenbuf, 0xdb, c->wbuf_pagesize); | 1133 | |
1202 | #endif | 1134 | return 0; |
1203 | return res; | ||
1204 | } | 1135 | } |
1205 | 1136 | ||
1206 | void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) | 1137 | void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) |
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index aa9132d04920..f7f8eff19b7b 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c | |||
@@ -88,7 +88,7 @@ static int jfs_release(struct inode *inode, struct file *file) | |||
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | struct inode_operations jfs_file_inode_operations = { | 91 | const struct inode_operations jfs_file_inode_operations = { |
92 | .truncate = jfs_truncate, | 92 | .truncate = jfs_truncate, |
93 | .setxattr = jfs_setxattr, | 93 | .setxattr = jfs_setxattr, |
94 | .getxattr = jfs_getxattr, | 94 | .getxattr = jfs_getxattr, |
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index 0d06ccfaff0e..6802837f757e 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h | |||
@@ -35,10 +35,10 @@ extern void jfs_set_inode_flags(struct inode *); | |||
35 | extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); | 35 | extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); |
36 | 36 | ||
37 | extern const struct address_space_operations jfs_aops; | 37 | extern const struct address_space_operations jfs_aops; |
38 | extern struct inode_operations jfs_dir_inode_operations; | 38 | extern const struct inode_operations jfs_dir_inode_operations; |
39 | extern const struct file_operations jfs_dir_operations; | 39 | extern const struct file_operations jfs_dir_operations; |
40 | extern struct inode_operations jfs_file_inode_operations; | 40 | extern const struct inode_operations jfs_file_inode_operations; |
41 | extern const struct file_operations jfs_file_operations; | 41 | extern const struct file_operations jfs_file_operations; |
42 | extern struct inode_operations jfs_symlink_inode_operations; | 42 | extern const struct inode_operations jfs_symlink_inode_operations; |
43 | extern struct dentry_operations jfs_ci_dentry_operations; | 43 | extern struct dentry_operations jfs_ci_dentry_operations; |
44 | #endif /* _H_JFS_INODE */ | 44 | #endif /* _H_JFS_INODE */ |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 7ab47561b68d..41c204771262 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -1503,7 +1503,7 @@ struct dentry *jfs_get_parent(struct dentry *dentry) | |||
1503 | return parent; | 1503 | return parent; |
1504 | } | 1504 | } |
1505 | 1505 | ||
1506 | struct inode_operations jfs_dir_inode_operations = { | 1506 | const struct inode_operations jfs_dir_inode_operations = { |
1507 | .create = jfs_create, | 1507 | .create = jfs_create, |
1508 | .lookup = jfs_lookup, | 1508 | .lookup = jfs_lookup, |
1509 | .link = jfs_link, | 1509 | .link = jfs_link, |
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 846ac8f34513..52d73d54a931 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); | |||
46 | 46 | ||
47 | static struct kmem_cache * jfs_inode_cachep; | 47 | static struct kmem_cache * jfs_inode_cachep; |
48 | 48 | ||
49 | static struct super_operations jfs_super_operations; | 49 | static const struct super_operations jfs_super_operations; |
50 | static struct export_operations jfs_export_operations; | 50 | static struct export_operations jfs_export_operations; |
51 | static struct file_system_type jfs_fs_type; | 51 | static struct file_system_type jfs_fs_type; |
52 | 52 | ||
@@ -716,7 +716,7 @@ out: | |||
716 | 716 | ||
717 | #endif | 717 | #endif |
718 | 718 | ||
719 | static struct super_operations jfs_super_operations = { | 719 | static const struct super_operations jfs_super_operations = { |
720 | .alloc_inode = jfs_alloc_inode, | 720 | .alloc_inode = jfs_alloc_inode, |
721 | .destroy_inode = jfs_destroy_inode, | 721 | .destroy_inode = jfs_destroy_inode, |
722 | .read_inode = jfs_read_inode, | 722 | .read_inode = jfs_read_inode, |
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c index cee43f36f51d..4af1a05aad0a 100644 --- a/fs/jfs/symlink.c +++ b/fs/jfs/symlink.c | |||
@@ -29,7 +29,7 @@ static void *jfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
29 | return NULL; | 29 | return NULL; |
30 | } | 30 | } |
31 | 31 | ||
32 | struct inode_operations jfs_symlink_inode_operations = { | 32 | const struct inode_operations jfs_symlink_inode_operations = { |
33 | .readlink = generic_readlink, | 33 | .readlink = generic_readlink, |
34 | .follow_link = jfs_follow_link, | 34 | .follow_link = jfs_follow_link, |
35 | .setxattr = jfs_setxattr, | 35 | .setxattr = jfs_setxattr, |
diff --git a/fs/libfs.c b/fs/libfs.c index 503898d5c4a7..cf79196535ec 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -186,7 +186,7 @@ const struct file_operations simple_dir_operations = { | |||
186 | .fsync = simple_sync_file, | 186 | .fsync = simple_sync_file, |
187 | }; | 187 | }; |
188 | 188 | ||
189 | struct inode_operations simple_dir_inode_operations = { | 189 | const struct inode_operations simple_dir_inode_operations = { |
190 | .lookup = simple_lookup, | 190 | .lookup = simple_lookup, |
191 | }; | 191 | }; |
192 | 192 | ||
@@ -195,11 +195,11 @@ struct inode_operations simple_dir_inode_operations = { | |||
195 | * will never be mountable) | 195 | * will never be mountable) |
196 | */ | 196 | */ |
197 | int get_sb_pseudo(struct file_system_type *fs_type, char *name, | 197 | int get_sb_pseudo(struct file_system_type *fs_type, char *name, |
198 | struct super_operations *ops, unsigned long magic, | 198 | const struct super_operations *ops, unsigned long magic, |
199 | struct vfsmount *mnt) | 199 | struct vfsmount *mnt) |
200 | { | 200 | { |
201 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); | 201 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); |
202 | static struct super_operations default_ops = {.statfs = simple_statfs}; | 202 | static const struct super_operations default_ops = {.statfs = simple_statfs}; |
203 | struct dentry *dentry; | 203 | struct dentry *dentry; |
204 | struct inode *root; | 204 | struct inode *root; |
205 | struct qstr d_name = {.name = name, .len = strlen(name)}; | 205 | struct qstr d_name = {.name = name, .len = strlen(name)}; |
@@ -335,17 +335,18 @@ int simple_prepare_write(struct file *file, struct page *page, | |||
335 | flush_dcache_page(page); | 335 | flush_dcache_page(page); |
336 | kunmap_atomic(kaddr, KM_USER0); | 336 | kunmap_atomic(kaddr, KM_USER0); |
337 | } | 337 | } |
338 | SetPageUptodate(page); | ||
339 | } | 338 | } |
340 | return 0; | 339 | return 0; |
341 | } | 340 | } |
342 | 341 | ||
343 | int simple_commit_write(struct file *file, struct page *page, | 342 | int simple_commit_write(struct file *file, struct page *page, |
344 | unsigned offset, unsigned to) | 343 | unsigned from, unsigned to) |
345 | { | 344 | { |
346 | struct inode *inode = page->mapping->host; | 345 | struct inode *inode = page->mapping->host; |
347 | loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; | 346 | loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; |
348 | 347 | ||
348 | if (!PageUptodate(page)) | ||
349 | SetPageUptodate(page); | ||
349 | /* | 350 | /* |
350 | * No need to use i_size_read() here, the i_size | 351 | * No need to use i_size_read() here, the i_size |
351 | * cannot change under us because we hold the i_mutex. | 352 | * cannot change under us because we hold the i_mutex. |
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 0b4acc1c5e7d..a5c019e1a447 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -361,7 +361,6 @@ static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message * | |||
361 | { | 361 | { |
362 | struct nlm_host *host = req->a_host; | 362 | struct nlm_host *host = req->a_host; |
363 | struct rpc_clnt *clnt; | 363 | struct rpc_clnt *clnt; |
364 | int status = -ENOLCK; | ||
365 | 364 | ||
366 | dprintk("lockd: call procedure %d on %s (async)\n", | 365 | dprintk("lockd: call procedure %d on %s (async)\n", |
367 | (int)proc, host->h_name); | 366 | (int)proc, host->h_name); |
@@ -373,12 +372,10 @@ static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message * | |||
373 | msg->rpc_proc = &clnt->cl_procinfo[proc]; | 372 | msg->rpc_proc = &clnt->cl_procinfo[proc]; |
374 | 373 | ||
375 | /* bootstrap and kick off the async RPC call */ | 374 | /* bootstrap and kick off the async RPC call */ |
376 | status = rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req); | 375 | return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req); |
377 | if (status == 0) | ||
378 | return 0; | ||
379 | out_err: | 376 | out_err: |
380 | nlm_release_call(req); | 377 | tk_ops->rpc_release(req); |
381 | return status; | 378 | return -ENOLCK; |
382 | } | 379 | } |
383 | 380 | ||
384 | int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) | 381 | int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) |
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 3d4610c2a266..ad21c0713efa 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -9,7 +9,6 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/sched.h> | ||
13 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
14 | #include <linux/in.h> | 13 | #include <linux/in.h> |
15 | #include <linux/sunrpc/clnt.h> | 14 | #include <linux/sunrpc/clnt.h> |
@@ -192,7 +191,7 @@ struct nlm_host * | |||
192 | nlmsvc_lookup_host(struct svc_rqst *rqstp, | 191 | nlmsvc_lookup_host(struct svc_rqst *rqstp, |
193 | const char *hostname, int hostname_len) | 192 | const char *hostname, int hostname_len) |
194 | { | 193 | { |
195 | return nlm_lookup_host(1, &rqstp->rq_addr, | 194 | return nlm_lookup_host(1, svc_addr_in(rqstp), |
196 | rqstp->rq_prot, rqstp->rq_vers, | 195 | rqstp->rq_prot, rqstp->rq_vers, |
197 | hostname, hostname_len); | 196 | hostname, hostname_len); |
198 | } | 197 | } |
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 8ca18085e68d..126b1bf02c0e 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
@@ -141,6 +141,7 @@ lockd(struct svc_rqst *rqstp) | |||
141 | */ | 141 | */ |
142 | while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) { | 142 | while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) { |
143 | long timeout = MAX_SCHEDULE_TIMEOUT; | 143 | long timeout = MAX_SCHEDULE_TIMEOUT; |
144 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
144 | 145 | ||
145 | if (signalled()) { | 146 | if (signalled()) { |
146 | flush_signals(current); | 147 | flush_signals(current); |
@@ -175,11 +176,10 @@ lockd(struct svc_rqst *rqstp) | |||
175 | break; | 176 | break; |
176 | } | 177 | } |
177 | 178 | ||
178 | dprintk("lockd: request from %08x\n", | 179 | dprintk("lockd: request from %s\n", |
179 | (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr)); | 180 | svc_print_addr(rqstp, buf, sizeof(buf))); |
180 | 181 | ||
181 | svc_process(rqstp); | 182 | svc_process(rqstp); |
182 | |||
183 | } | 183 | } |
184 | 184 | ||
185 | flush_signals(current); | 185 | flush_signals(current); |
@@ -223,23 +223,29 @@ static int find_socket(struct svc_serv *serv, int proto) | |||
223 | return found; | 223 | return found; |
224 | } | 224 | } |
225 | 225 | ||
226 | /* | ||
227 | * Make any sockets that are needed but not present. | ||
228 | * If nlm_udpport or nlm_tcpport were set as module | ||
229 | * options, make those sockets unconditionally | ||
230 | */ | ||
226 | static int make_socks(struct svc_serv *serv, int proto) | 231 | static int make_socks(struct svc_serv *serv, int proto) |
227 | { | 232 | { |
228 | /* Make any sockets that are needed but not present. | 233 | static int warned; |
229 | * If nlm_udpport or nlm_tcpport were set as module | ||
230 | * options, make those sockets unconditionally | ||
231 | */ | ||
232 | static int warned; | ||
233 | int err = 0; | 234 | int err = 0; |
235 | |||
234 | if (proto == IPPROTO_UDP || nlm_udpport) | 236 | if (proto == IPPROTO_UDP || nlm_udpport) |
235 | if (!find_socket(serv, IPPROTO_UDP)) | 237 | if (!find_socket(serv, IPPROTO_UDP)) |
236 | err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport); | 238 | err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport, |
237 | if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport)) | 239 | SVC_SOCK_DEFAULTS); |
240 | if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) | ||
238 | if (!find_socket(serv, IPPROTO_TCP)) | 241 | if (!find_socket(serv, IPPROTO_TCP)) |
239 | err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport); | 242 | err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport, |
240 | if (!err) | 243 | SVC_SOCK_DEFAULTS); |
244 | |||
245 | if (err >= 0) { | ||
241 | warned = 0; | 246 | warned = 0; |
242 | else if (warned++ == 0) | 247 | err = 0; |
248 | } else if (warned++ == 0) | ||
243 | printk(KERN_WARNING | 249 | printk(KERN_WARNING |
244 | "lockd_up: makesock failed, error=%d\n", err); | 250 | "lockd_up: makesock failed, error=%d\n", err); |
245 | return err; | 251 | return err; |
@@ -434,7 +440,7 @@ static ctl_table nlm_sysctl_root[] = { | |||
434 | }; | 440 | }; |
435 | 441 | ||
436 | /* | 442 | /* |
437 | * Module (and driverfs) parameters. | 443 | * Module (and sysfs) parameters. |
438 | */ | 444 | */ |
439 | 445 | ||
440 | #define param_set_min_max(name, type, which_strtol, min, max) \ | 446 | #define param_set_min_max(name, type, which_strtol, min, max) \ |
@@ -506,7 +512,7 @@ module_param(nsm_use_hostnames, bool, 0644); | |||
506 | 512 | ||
507 | static int __init init_nlm(void) | 513 | static int __init init_nlm(void) |
508 | { | 514 | { |
509 | nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root, 0); | 515 | nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root); |
510 | return nlm_sysctl_table ? 0 : -ENOMEM; | 516 | return nlm_sysctl_table ? 0 : -ENOMEM; |
511 | } | 517 | } |
512 | 518 | ||
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index f67146a8199a..47a66aa5d55b 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c | |||
@@ -224,7 +224,7 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
224 | resp->cookie = argp->cookie; | 224 | resp->cookie = argp->cookie; |
225 | 225 | ||
226 | dprintk("lockd: GRANTED called\n"); | 226 | dprintk("lockd: GRANTED called\n"); |
227 | resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock); | 227 | resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock); |
228 | dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); | 228 | dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); |
229 | return rpc_success; | 229 | return rpc_success; |
230 | } | 230 | } |
@@ -421,15 +421,16 @@ static __be32 | |||
421 | nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, | 421 | nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, |
422 | void *resp) | 422 | void *resp) |
423 | { | 423 | { |
424 | struct sockaddr_in saddr = rqstp->rq_addr; | 424 | struct sockaddr_in saddr; |
425 | |||
426 | memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr)); | ||
425 | 427 | ||
426 | dprintk("lockd: SM_NOTIFY called\n"); | 428 | dprintk("lockd: SM_NOTIFY called\n"); |
427 | if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) | 429 | if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) |
428 | || ntohs(saddr.sin_port) >= 1024) { | 430 | || ntohs(saddr.sin_port) >= 1024) { |
429 | printk(KERN_WARNING | 431 | char buf[RPC_MAX_ADDRBUFLEN]; |
430 | "lockd: rejected NSM callback from %08x:%d\n", | 432 | printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", |
431 | ntohl(rqstp->rq_addr.sin_addr.s_addr), | 433 | svc_print_addr(rqstp, buf, sizeof(buf))); |
432 | ntohs(rqstp->rq_addr.sin_port)); | ||
433 | return rpc_system_err; | 434 | return rpc_system_err; |
434 | } | 435 | } |
435 | 436 | ||
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index c7db0a5bccdc..cf51f849e76c 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -593,9 +593,7 @@ callback: | |||
593 | 593 | ||
594 | /* Call the client */ | 594 | /* Call the client */ |
595 | kref_get(&block->b_count); | 595 | kref_get(&block->b_count); |
596 | if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, | 596 | nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops); |
597 | &nlmsvc_grant_ops) < 0) | ||
598 | nlmsvc_release_block(block); | ||
599 | } | 597 | } |
600 | 598 | ||
601 | /* | 599 | /* |
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 3707c3a23e93..31cb48425733 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
@@ -253,7 +253,7 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
253 | resp->cookie = argp->cookie; | 253 | resp->cookie = argp->cookie; |
254 | 254 | ||
255 | dprintk("lockd: GRANTED called\n"); | 255 | dprintk("lockd: GRANTED called\n"); |
256 | resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock); | 256 | resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock); |
257 | dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); | 257 | dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); |
258 | return rpc_success; | 258 | return rpc_success; |
259 | } | 259 | } |
@@ -452,15 +452,16 @@ static __be32 | |||
452 | nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, | 452 | nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, |
453 | void *resp) | 453 | void *resp) |
454 | { | 454 | { |
455 | struct sockaddr_in saddr = rqstp->rq_addr; | 455 | struct sockaddr_in saddr; |
456 | |||
457 | memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr)); | ||
456 | 458 | ||
457 | dprintk("lockd: SM_NOTIFY called\n"); | 459 | dprintk("lockd: SM_NOTIFY called\n"); |
458 | if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) | 460 | if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) |
459 | || ntohs(saddr.sin_port) >= 1024) { | 461 | || ntohs(saddr.sin_port) >= 1024) { |
460 | printk(KERN_WARNING | 462 | char buf[RPC_MAX_ADDRBUFLEN]; |
461 | "lockd: rejected NSM callback from %08x:%d\n", | 463 | printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", |
462 | ntohl(rqstp->rq_addr.sin_addr.s_addr), | 464 | svc_print_addr(rqstp, buf, sizeof(buf))); |
463 | ntohs(rqstp->rq_addr.sin_port)); | ||
464 | return rpc_system_err; | 465 | return rpc_system_err; |
465 | } | 466 | } |
466 | 467 | ||
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index df6b1075b549..c4a554df7b7e 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c | |||
@@ -26,14 +26,14 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _ | |||
26 | for (i=0; i<numblocks-1; i++) { | 26 | for (i=0; i<numblocks-1; i++) { |
27 | if (!(bh=map[i])) | 27 | if (!(bh=map[i])) |
28 | return(0); | 28 | return(0); |
29 | for (j=0; j<BLOCK_SIZE; j++) | 29 | for (j=0; j<bh->b_size; j++) |
30 | sum += nibblemap[bh->b_data[j] & 0xf] | 30 | sum += nibblemap[bh->b_data[j] & 0xf] |
31 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; | 31 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; |
32 | } | 32 | } |
33 | 33 | ||
34 | if (numblocks==0 || !(bh=map[numblocks-1])) | 34 | if (numblocks==0 || !(bh=map[numblocks-1])) |
35 | return(0); | 35 | return(0); |
36 | i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2; | 36 | i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2; |
37 | for (j=0; j<i; j++) { | 37 | for (j=0; j<i; j++) { |
38 | sum += nibblemap[bh->b_data[j] & 0xf] | 38 | sum += nibblemap[bh->b_data[j] & 0xf] |
39 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; | 39 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; |
@@ -48,28 +48,29 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _ | |||
48 | return(sum); | 48 | return(sum); |
49 | } | 49 | } |
50 | 50 | ||
51 | void minix_free_block(struct inode * inode, int block) | 51 | void minix_free_block(struct inode *inode, unsigned long block) |
52 | { | 52 | { |
53 | struct super_block * sb = inode->i_sb; | 53 | struct super_block *sb = inode->i_sb; |
54 | struct minix_sb_info * sbi = minix_sb(sb); | 54 | struct minix_sb_info *sbi = minix_sb(sb); |
55 | struct buffer_head * bh; | 55 | struct buffer_head *bh; |
56 | unsigned int bit,zone; | 56 | int k = sb->s_blocksize_bits + 3; |
57 | unsigned long bit, zone; | ||
57 | 58 | ||
58 | if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) { | 59 | if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) { |
59 | printk("Trying to free block not in datazone\n"); | 60 | printk("Trying to free block not in datazone\n"); |
60 | return; | 61 | return; |
61 | } | 62 | } |
62 | zone = block - sbi->s_firstdatazone + 1; | 63 | zone = block - sbi->s_firstdatazone + 1; |
63 | bit = zone & 8191; | 64 | bit = zone & ((1<<k) - 1); |
64 | zone >>= 13; | 65 | zone >>= k; |
65 | if (zone >= sbi->s_zmap_blocks) { | 66 | if (zone >= sbi->s_zmap_blocks) { |
66 | printk("minix_free_block: nonexistent bitmap buffer\n"); | 67 | printk("minix_free_block: nonexistent bitmap buffer\n"); |
67 | return; | 68 | return; |
68 | } | 69 | } |
69 | bh = sbi->s_zmap[zone]; | 70 | bh = sbi->s_zmap[zone]; |
70 | lock_kernel(); | 71 | lock_kernel(); |
71 | if (!minix_test_and_clear_bit(bit,bh->b_data)) | 72 | if (!minix_test_and_clear_bit(bit, bh->b_data)) |
72 | printk("free_block (%s:%d): bit already cleared\n", | 73 | printk("minix_free_block (%s:%lu): bit already cleared\n", |
73 | sb->s_id, block); | 74 | sb->s_id, block); |
74 | unlock_kernel(); | 75 | unlock_kernel(); |
75 | mark_buffer_dirty(bh); | 76 | mark_buffer_dirty(bh); |
@@ -79,6 +80,7 @@ void minix_free_block(struct inode * inode, int block) | |||
79 | int minix_new_block(struct inode * inode) | 80 | int minix_new_block(struct inode * inode) |
80 | { | 81 | { |
81 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); | 82 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); |
83 | int bits_per_zone = 8 * inode->i_sb->s_blocksize; | ||
82 | int i; | 84 | int i; |
83 | 85 | ||
84 | for (i = 0; i < sbi->s_zmap_blocks; i++) { | 86 | for (i = 0; i < sbi->s_zmap_blocks; i++) { |
@@ -86,11 +88,12 @@ int minix_new_block(struct inode * inode) | |||
86 | int j; | 88 | int j; |
87 | 89 | ||
88 | lock_kernel(); | 90 | lock_kernel(); |
89 | if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) { | 91 | j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); |
90 | minix_set_bit(j,bh->b_data); | 92 | if (j < bits_per_zone) { |
93 | minix_set_bit(j, bh->b_data); | ||
91 | unlock_kernel(); | 94 | unlock_kernel(); |
92 | mark_buffer_dirty(bh); | 95 | mark_buffer_dirty(bh); |
93 | j += i*8192 + sbi->s_firstdatazone-1; | 96 | j += i * bits_per_zone + sbi->s_firstdatazone-1; |
94 | if (j < sbi->s_firstdatazone || j >= sbi->s_nzones) | 97 | if (j < sbi->s_firstdatazone || j >= sbi->s_nzones) |
95 | break; | 98 | break; |
96 | return j; | 99 | return j; |
@@ -137,6 +140,7 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh) | |||
137 | int block; | 140 | int block; |
138 | struct minix_sb_info *sbi = minix_sb(sb); | 141 | struct minix_sb_info *sbi = minix_sb(sb); |
139 | struct minix2_inode *p; | 142 | struct minix2_inode *p; |
143 | int minix2_inodes_per_block = sb->s_blocksize / sizeof(struct minix2_inode); | ||
140 | 144 | ||
141 | *bh = NULL; | 145 | *bh = NULL; |
142 | if (!ino || ino > sbi->s_ninodes) { | 146 | if (!ino || ino > sbi->s_ninodes) { |
@@ -146,14 +150,14 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh) | |||
146 | } | 150 | } |
147 | ino--; | 151 | ino--; |
148 | block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks + | 152 | block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks + |
149 | ino / MINIX2_INODES_PER_BLOCK; | 153 | ino / minix2_inodes_per_block; |
150 | *bh = sb_bread(sb, block); | 154 | *bh = sb_bread(sb, block); |
151 | if (!*bh) { | 155 | if (!*bh) { |
152 | printk("Unable to read inode block\n"); | 156 | printk("Unable to read inode block\n"); |
153 | return NULL; | 157 | return NULL; |
154 | } | 158 | } |
155 | p = (void *)(*bh)->b_data; | 159 | p = (void *)(*bh)->b_data; |
156 | return p + ino % MINIX2_INODES_PER_BLOCK; | 160 | return p + ino % minix2_inodes_per_block; |
157 | } | 161 | } |
158 | 162 | ||
159 | /* Clear the link count and mode of a deleted inode on disk. */ | 163 | /* Clear the link count and mode of a deleted inode on disk. */ |
@@ -185,26 +189,30 @@ static void minix_clear_inode(struct inode *inode) | |||
185 | 189 | ||
186 | void minix_free_inode(struct inode * inode) | 190 | void minix_free_inode(struct inode * inode) |
187 | { | 191 | { |
192 | struct super_block *sb = inode->i_sb; | ||
188 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); | 193 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); |
189 | struct buffer_head * bh; | 194 | struct buffer_head *bh; |
190 | unsigned long ino; | 195 | int k = sb->s_blocksize_bits + 3; |
196 | unsigned long ino, bit; | ||
191 | 197 | ||
192 | ino = inode->i_ino; | 198 | ino = inode->i_ino; |
193 | if (ino < 1 || ino > sbi->s_ninodes) { | 199 | if (ino < 1 || ino > sbi->s_ninodes) { |
194 | printk("minix_free_inode: inode 0 or nonexistent inode\n"); | 200 | printk("minix_free_inode: inode 0 or nonexistent inode\n"); |
195 | goto out; | 201 | goto out; |
196 | } | 202 | } |
197 | if ((ino >> 13) >= sbi->s_imap_blocks) { | 203 | bit = ino & ((1<<k) - 1); |
204 | ino >>= k; | ||
205 | if (ino >= sbi->s_imap_blocks) { | ||
198 | printk("minix_free_inode: nonexistent imap in superblock\n"); | 206 | printk("minix_free_inode: nonexistent imap in superblock\n"); |
199 | goto out; | 207 | goto out; |
200 | } | 208 | } |
201 | 209 | ||
202 | minix_clear_inode(inode); /* clear on-disk copy */ | 210 | minix_clear_inode(inode); /* clear on-disk copy */ |
203 | 211 | ||
204 | bh = sbi->s_imap[ino >> 13]; | 212 | bh = sbi->s_imap[ino]; |
205 | lock_kernel(); | 213 | lock_kernel(); |
206 | if (!minix_test_and_clear_bit(ino & 8191, bh->b_data)) | 214 | if (!minix_test_and_clear_bit(bit, bh->b_data)) |
207 | printk("minix_free_inode: bit %lu already cleared\n", ino); | 215 | printk("minix_free_inode: bit %lu already cleared\n", bit); |
208 | unlock_kernel(); | 216 | unlock_kernel(); |
209 | mark_buffer_dirty(bh); | 217 | mark_buffer_dirty(bh); |
210 | out: | 218 | out: |
@@ -217,35 +225,38 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) | |||
217 | struct minix_sb_info *sbi = minix_sb(sb); | 225 | struct minix_sb_info *sbi = minix_sb(sb); |
218 | struct inode *inode = new_inode(sb); | 226 | struct inode *inode = new_inode(sb); |
219 | struct buffer_head * bh; | 227 | struct buffer_head * bh; |
220 | int i,j; | 228 | int bits_per_zone = 8 * sb->s_blocksize; |
229 | unsigned long j; | ||
230 | int i; | ||
221 | 231 | ||
222 | if (!inode) { | 232 | if (!inode) { |
223 | *error = -ENOMEM; | 233 | *error = -ENOMEM; |
224 | return NULL; | 234 | return NULL; |
225 | } | 235 | } |
226 | j = 8192; | 236 | j = bits_per_zone; |
227 | bh = NULL; | 237 | bh = NULL; |
228 | *error = -ENOSPC; | 238 | *error = -ENOSPC; |
229 | lock_kernel(); | 239 | lock_kernel(); |
230 | for (i = 0; i < sbi->s_imap_blocks; i++) { | 240 | for (i = 0; i < sbi->s_imap_blocks; i++) { |
231 | bh = sbi->s_imap[i]; | 241 | bh = sbi->s_imap[i]; |
232 | if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) | 242 | j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); |
243 | if (j < bits_per_zone) | ||
233 | break; | 244 | break; |
234 | } | 245 | } |
235 | if (!bh || j >= 8192) { | 246 | if (!bh || j >= bits_per_zone) { |
236 | unlock_kernel(); | 247 | unlock_kernel(); |
237 | iput(inode); | 248 | iput(inode); |
238 | return NULL; | 249 | return NULL; |
239 | } | 250 | } |
240 | if (minix_test_and_set_bit(j,bh->b_data)) { /* shouldn't happen */ | 251 | if (minix_test_and_set_bit(j, bh->b_data)) { /* shouldn't happen */ |
241 | printk("new_inode: bit already set\n"); | ||
242 | unlock_kernel(); | 252 | unlock_kernel(); |
253 | printk("minix_new_inode: bit already set\n"); | ||
243 | iput(inode); | 254 | iput(inode); |
244 | return NULL; | 255 | return NULL; |
245 | } | 256 | } |
246 | unlock_kernel(); | 257 | unlock_kernel(); |
247 | mark_buffer_dirty(bh); | 258 | mark_buffer_dirty(bh); |
248 | j += i*8192; | 259 | j += i * bits_per_zone; |
249 | if (!j || j > sbi->s_ninodes) { | 260 | if (!j || j > sbi->s_ninodes) { |
250 | iput(inode); | 261 | iput(inode); |
251 | return NULL; | 262 | return NULL; |
diff --git a/fs/minix/dir.c b/fs/minix/dir.c index ab782c4086f5..cb4cb571fddf 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 4 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * | 5 | * |
6 | * minix directory handling functions | 6 | * minix directory handling functions |
7 | * | ||
8 | * Updated to filesystem version 3 by Daniel Aragones | ||
7 | */ | 9 | */ |
8 | 10 | ||
9 | #include "minix.h" | 11 | #include "minix.h" |
@@ -11,6 +13,7 @@ | |||
11 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
12 | 14 | ||
13 | typedef struct minix_dir_entry minix_dirent; | 15 | typedef struct minix_dir_entry minix_dirent; |
16 | typedef struct minix3_dir_entry minix3_dirent; | ||
14 | 17 | ||
15 | static int minix_readdir(struct file *, void *, filldir_t); | 18 | static int minix_readdir(struct file *, void *, filldir_t); |
16 | 19 | ||
@@ -89,6 +92,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
89 | unsigned long npages = dir_pages(inode); | 92 | unsigned long npages = dir_pages(inode); |
90 | struct minix_sb_info *sbi = minix_sb(sb); | 93 | struct minix_sb_info *sbi = minix_sb(sb); |
91 | unsigned chunk_size = sbi->s_dirsize; | 94 | unsigned chunk_size = sbi->s_dirsize; |
95 | char *name; | ||
96 | __u32 inumber; | ||
92 | 97 | ||
93 | lock_kernel(); | 98 | lock_kernel(); |
94 | 99 | ||
@@ -105,16 +110,24 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
105 | kaddr = (char *)page_address(page); | 110 | kaddr = (char *)page_address(page); |
106 | p = kaddr+offset; | 111 | p = kaddr+offset; |
107 | limit = kaddr + minix_last_byte(inode, n) - chunk_size; | 112 | limit = kaddr + minix_last_byte(inode, n) - chunk_size; |
108 | for ( ; p <= limit ; p = minix_next_entry(p, sbi)) { | 113 | for ( ; p <= limit; p = minix_next_entry(p, sbi)) { |
109 | minix_dirent *de = (minix_dirent *)p; | 114 | if (sbi->s_version == MINIX_V3) { |
110 | if (de->inode) { | 115 | minix3_dirent *de3 = (minix3_dirent *)p; |
116 | name = de3->name; | ||
117 | inumber = de3->inode; | ||
118 | } else { | ||
119 | minix_dirent *de = (minix_dirent *)p; | ||
120 | name = de->name; | ||
121 | inumber = de->inode; | ||
122 | } | ||
123 | if (inumber) { | ||
111 | int over; | 124 | int over; |
112 | unsigned l = strnlen(de->name,sbi->s_namelen); | ||
113 | 125 | ||
126 | unsigned l = strnlen(name, sbi->s_namelen); | ||
114 | offset = p - kaddr; | 127 | offset = p - kaddr; |
115 | over = filldir(dirent, de->name, l, | 128 | over = filldir(dirent, name, l, |
116 | (n<<PAGE_CACHE_SHIFT) | offset, | 129 | (n << PAGE_CACHE_SHIFT) | offset, |
117 | de->inode, DT_UNKNOWN); | 130 | inumber, DT_UNKNOWN); |
118 | if (over) { | 131 | if (over) { |
119 | dir_put_page(page); | 132 | dir_put_page(page); |
120 | goto done; | 133 | goto done; |
@@ -156,23 +169,34 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page) | |||
156 | unsigned long n; | 169 | unsigned long n; |
157 | unsigned long npages = dir_pages(dir); | 170 | unsigned long npages = dir_pages(dir); |
158 | struct page *page = NULL; | 171 | struct page *page = NULL; |
159 | struct minix_dir_entry *de; | 172 | char *p; |
160 | 173 | ||
174 | char *namx; | ||
175 | __u32 inumber; | ||
161 | *res_page = NULL; | 176 | *res_page = NULL; |
162 | 177 | ||
163 | for (n = 0; n < npages; n++) { | 178 | for (n = 0; n < npages; n++) { |
164 | char *kaddr; | 179 | char *kaddr, *limit; |
180 | |||
165 | page = dir_get_page(dir, n); | 181 | page = dir_get_page(dir, n); |
166 | if (IS_ERR(page)) | 182 | if (IS_ERR(page)) |
167 | continue; | 183 | continue; |
168 | 184 | ||
169 | kaddr = (char*)page_address(page); | 185 | kaddr = (char*)page_address(page); |
170 | de = (struct minix_dir_entry *) kaddr; | 186 | limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize; |
171 | kaddr += minix_last_byte(dir, n) - sbi->s_dirsize; | 187 | for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) { |
172 | for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) { | 188 | if (sbi->s_version == MINIX_V3) { |
173 | if (!de->inode) | 189 | minix3_dirent *de3 = (minix3_dirent *)p; |
190 | namx = de3->name; | ||
191 | inumber = de3->inode; | ||
192 | } else { | ||
193 | minix_dirent *de = (minix_dirent *)p; | ||
194 | namx = de->name; | ||
195 | inumber = de->inode; | ||
196 | } | ||
197 | if (!inumber) | ||
174 | continue; | 198 | continue; |
175 | if (namecompare(namelen,sbi->s_namelen,name,de->name)) | 199 | if (namecompare(namelen, sbi->s_namelen, name, namx)) |
176 | goto found; | 200 | goto found; |
177 | } | 201 | } |
178 | dir_put_page(page); | 202 | dir_put_page(page); |
@@ -181,7 +205,7 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page) | |||
181 | 205 | ||
182 | found: | 206 | found: |
183 | *res_page = page; | 207 | *res_page = page; |
184 | return de; | 208 | return (minix_dirent *)p; |
185 | } | 209 | } |
186 | 210 | ||
187 | int minix_add_link(struct dentry *dentry, struct inode *inode) | 211 | int minix_add_link(struct dentry *dentry, struct inode *inode) |
@@ -192,12 +216,15 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) | |||
192 | struct super_block * sb = dir->i_sb; | 216 | struct super_block * sb = dir->i_sb; |
193 | struct minix_sb_info * sbi = minix_sb(sb); | 217 | struct minix_sb_info * sbi = minix_sb(sb); |
194 | struct page *page = NULL; | 218 | struct page *page = NULL; |
195 | struct minix_dir_entry * de; | ||
196 | unsigned long npages = dir_pages(dir); | 219 | unsigned long npages = dir_pages(dir); |
197 | unsigned long n; | 220 | unsigned long n; |
198 | char *kaddr; | 221 | char *kaddr, *p; |
222 | minix_dirent *de; | ||
223 | minix3_dirent *de3; | ||
199 | unsigned from, to; | 224 | unsigned from, to; |
200 | int err; | 225 | int err; |
226 | char *namx = NULL; | ||
227 | __u32 inumber; | ||
201 | 228 | ||
202 | /* | 229 | /* |
203 | * We take care of directory expansion in the same loop | 230 | * We take care of directory expansion in the same loop |
@@ -205,7 +232,7 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) | |||
205 | * to protect that region. | 232 | * to protect that region. |
206 | */ | 233 | */ |
207 | for (n = 0; n <= npages; n++) { | 234 | for (n = 0; n <= npages; n++) { |
208 | char *dir_end; | 235 | char *limit, *dir_end; |
209 | 236 | ||
210 | page = dir_get_page(dir, n); | 237 | page = dir_get_page(dir, n); |
211 | err = PTR_ERR(page); | 238 | err = PTR_ERR(page); |
@@ -214,20 +241,30 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) | |||
214 | lock_page(page); | 241 | lock_page(page); |
215 | kaddr = (char*)page_address(page); | 242 | kaddr = (char*)page_address(page); |
216 | dir_end = kaddr + minix_last_byte(dir, n); | 243 | dir_end = kaddr + minix_last_byte(dir, n); |
217 | de = (minix_dirent *)kaddr; | 244 | limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize; |
218 | kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize; | 245 | for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) { |
219 | while ((char *)de <= kaddr) { | 246 | de = (minix_dirent *)p; |
220 | if ((char *)de == dir_end) { | 247 | de3 = (minix3_dirent *)p; |
248 | if (sbi->s_version == MINIX_V3) { | ||
249 | namx = de3->name; | ||
250 | inumber = de3->inode; | ||
251 | } else { | ||
252 | namx = de->name; | ||
253 | inumber = de->inode; | ||
254 | } | ||
255 | if (p == dir_end) { | ||
221 | /* We hit i_size */ | 256 | /* We hit i_size */ |
222 | de->inode = 0; | 257 | if (sbi->s_version == MINIX_V3) |
258 | de3->inode = 0; | ||
259 | else | ||
260 | de->inode = 0; | ||
223 | goto got_it; | 261 | goto got_it; |
224 | } | 262 | } |
225 | if (!de->inode) | 263 | if (!inumber) |
226 | goto got_it; | 264 | goto got_it; |
227 | err = -EEXIST; | 265 | err = -EEXIST; |
228 | if (namecompare(namelen,sbi->s_namelen,name,de->name)) | 266 | if (namecompare(namelen, sbi->s_namelen, name, namx)) |
229 | goto out_unlock; | 267 | goto out_unlock; |
230 | de = minix_next_entry(de, sbi); | ||
231 | } | 268 | } |
232 | unlock_page(page); | 269 | unlock_page(page); |
233 | dir_put_page(page); | 270 | dir_put_page(page); |
@@ -236,14 +273,19 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) | |||
236 | return -EINVAL; | 273 | return -EINVAL; |
237 | 274 | ||
238 | got_it: | 275 | got_it: |
239 | from = (char*)de - (char*)page_address(page); | 276 | from = p - (char*)page_address(page); |
240 | to = from + sbi->s_dirsize; | 277 | to = from + sbi->s_dirsize; |
241 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 278 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); |
242 | if (err) | 279 | if (err) |
243 | goto out_unlock; | 280 | goto out_unlock; |
244 | memcpy (de->name, name, namelen); | 281 | memcpy (namx, name, namelen); |
245 | memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2); | 282 | if (sbi->s_version == MINIX_V3) { |
246 | de->inode = inode->i_ino; | 283 | memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4); |
284 | de3->inode = inode->i_ino; | ||
285 | } else { | ||
286 | memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2); | ||
287 | de->inode = inode->i_ino; | ||
288 | } | ||
247 | err = dir_commit_chunk(page, from, to); | 289 | err = dir_commit_chunk(page, from, to); |
248 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 290 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
249 | mark_inode_dirty(dir); | 291 | mark_inode_dirty(dir); |
@@ -283,8 +325,7 @@ int minix_make_empty(struct inode *inode, struct inode *dir) | |||
283 | { | 325 | { |
284 | struct address_space *mapping = inode->i_mapping; | 326 | struct address_space *mapping = inode->i_mapping; |
285 | struct page *page = grab_cache_page(mapping, 0); | 327 | struct page *page = grab_cache_page(mapping, 0); |
286 | struct minix_sb_info * sbi = minix_sb(inode->i_sb); | 328 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); |
287 | struct minix_dir_entry * de; | ||
288 | char *kaddr; | 329 | char *kaddr; |
289 | int err; | 330 | int err; |
290 | 331 | ||
@@ -299,12 +340,23 @@ int minix_make_empty(struct inode *inode, struct inode *dir) | |||
299 | kaddr = kmap_atomic(page, KM_USER0); | 340 | kaddr = kmap_atomic(page, KM_USER0); |
300 | memset(kaddr, 0, PAGE_CACHE_SIZE); | 341 | memset(kaddr, 0, PAGE_CACHE_SIZE); |
301 | 342 | ||
302 | de = (struct minix_dir_entry *)kaddr; | 343 | if (sbi->s_version == MINIX_V3) { |
303 | de->inode = inode->i_ino; | 344 | minix3_dirent *de3 = (minix3_dirent *)kaddr; |
304 | strcpy(de->name,"."); | 345 | |
305 | de = minix_next_entry(de, sbi); | 346 | de3->inode = inode->i_ino; |
306 | de->inode = dir->i_ino; | 347 | strcpy(de3->name, "."); |
307 | strcpy(de->name,".."); | 348 | de3 = minix_next_entry(de3, sbi); |
349 | de3->inode = dir->i_ino; | ||
350 | strcpy(de3->name, ".."); | ||
351 | } else { | ||
352 | minix_dirent *de = (minix_dirent *)kaddr; | ||
353 | |||
354 | de->inode = inode->i_ino; | ||
355 | strcpy(de->name, "."); | ||
356 | de = minix_next_entry(de, sbi); | ||
357 | de->inode = dir->i_ino; | ||
358 | strcpy(de->name, ".."); | ||
359 | } | ||
308 | kunmap_atomic(kaddr, KM_USER0); | 360 | kunmap_atomic(kaddr, KM_USER0); |
309 | 361 | ||
310 | err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize); | 362 | err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize); |
@@ -321,33 +373,41 @@ int minix_empty_dir(struct inode * inode) | |||
321 | struct page *page = NULL; | 373 | struct page *page = NULL; |
322 | unsigned long i, npages = dir_pages(inode); | 374 | unsigned long i, npages = dir_pages(inode); |
323 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); | 375 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); |
376 | char *name; | ||
377 | __u32 inumber; | ||
324 | 378 | ||
325 | for (i = 0; i < npages; i++) { | 379 | for (i = 0; i < npages; i++) { |
326 | char *kaddr; | 380 | char *p, *kaddr, *limit; |
327 | minix_dirent * de; | ||
328 | page = dir_get_page(inode, i); | ||
329 | 381 | ||
382 | page = dir_get_page(inode, i); | ||
330 | if (IS_ERR(page)) | 383 | if (IS_ERR(page)) |
331 | continue; | 384 | continue; |
332 | 385 | ||
333 | kaddr = (char *)page_address(page); | 386 | kaddr = (char *)page_address(page); |
334 | de = (minix_dirent *)kaddr; | 387 | limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize; |
335 | kaddr += minix_last_byte(inode, i) - sbi->s_dirsize; | 388 | for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) { |
389 | if (sbi->s_version == MINIX_V3) { | ||
390 | minix3_dirent *de3 = (minix3_dirent *)p; | ||
391 | name = de3->name; | ||
392 | inumber = de3->inode; | ||
393 | } else { | ||
394 | minix_dirent *de = (minix_dirent *)p; | ||
395 | name = de->name; | ||
396 | inumber = de->inode; | ||
397 | } | ||
336 | 398 | ||
337 | while ((char *)de <= kaddr) { | 399 | if (inumber != 0) { |
338 | if (de->inode != 0) { | ||
339 | /* check for . and .. */ | 400 | /* check for . and .. */ |
340 | if (de->name[0] != '.') | 401 | if (name[0] != '.') |
341 | goto not_empty; | 402 | goto not_empty; |
342 | if (!de->name[1]) { | 403 | if (!name[1]) { |
343 | if (de->inode != inode->i_ino) | 404 | if (inumber != inode->i_ino) |
344 | goto not_empty; | 405 | goto not_empty; |
345 | } else if (de->name[1] != '.') | 406 | } else if (name[1] != '.') |
346 | goto not_empty; | 407 | goto not_empty; |
347 | else if (de->name[2]) | 408 | else if (name[2]) |
348 | goto not_empty; | 409 | goto not_empty; |
349 | } | 410 | } |
350 | de = minix_next_entry(de, sbi); | ||
351 | } | 411 | } |
352 | dir_put_page(page); | 412 | dir_put_page(page); |
353 | } | 413 | } |
diff --git a/fs/minix/file.c b/fs/minix/file.c index 40eac2e60d25..f92baa1d7570 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c | |||
@@ -26,7 +26,7 @@ const struct file_operations minix_file_operations = { | |||
26 | .sendfile = generic_file_sendfile, | 26 | .sendfile = generic_file_sendfile, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | struct inode_operations minix_file_inode_operations = { | 29 | const struct inode_operations minix_file_inode_operations = { |
30 | .truncate = minix_truncate, | 30 | .truncate = minix_truncate, |
31 | .getattr = minix_getattr, | 31 | .getattr = minix_getattr, |
32 | }; | 32 | }; |
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 629e09b38c5c..92e383af3709 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Minix V2 fs support. | 7 | * Minix V2 fs support. |
8 | * | 8 | * |
9 | * Modified for 680x0 by Andreas Schwab | 9 | * Modified for 680x0 by Andreas Schwab |
10 | * Updated to filesystem version 3 by Daniel Aragones | ||
10 | */ | 11 | */ |
11 | 12 | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
@@ -36,7 +37,8 @@ static void minix_put_super(struct super_block *sb) | |||
36 | struct minix_sb_info *sbi = minix_sb(sb); | 37 | struct minix_sb_info *sbi = minix_sb(sb); |
37 | 38 | ||
38 | if (!(sb->s_flags & MS_RDONLY)) { | 39 | if (!(sb->s_flags & MS_RDONLY)) { |
39 | sbi->s_ms->s_state = sbi->s_mount_state; | 40 | if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ |
41 | sbi->s_ms->s_state = sbi->s_mount_state; | ||
40 | mark_buffer_dirty(sbi->s_sbh); | 42 | mark_buffer_dirty(sbi->s_sbh); |
41 | } | 43 | } |
42 | for (i = 0; i < sbi->s_imap_blocks; i++) | 44 | for (i = 0; i < sbi->s_imap_blocks; i++) |
@@ -93,7 +95,7 @@ static void destroy_inodecache(void) | |||
93 | kmem_cache_destroy(minix_inode_cachep); | 95 | kmem_cache_destroy(minix_inode_cachep); |
94 | } | 96 | } |
95 | 97 | ||
96 | static struct super_operations minix_sops = { | 98 | static const struct super_operations minix_sops = { |
97 | .alloc_inode = minix_alloc_inode, | 99 | .alloc_inode = minix_alloc_inode, |
98 | .destroy_inode = minix_destroy_inode, | 100 | .destroy_inode = minix_destroy_inode, |
99 | .read_inode = minix_read_inode, | 101 | .read_inode = minix_read_inode, |
@@ -117,12 +119,17 @@ static int minix_remount (struct super_block * sb, int * flags, char * data) | |||
117 | !(sbi->s_mount_state & MINIX_VALID_FS)) | 119 | !(sbi->s_mount_state & MINIX_VALID_FS)) |
118 | return 0; | 120 | return 0; |
119 | /* Mounting a rw partition read-only. */ | 121 | /* Mounting a rw partition read-only. */ |
120 | ms->s_state = sbi->s_mount_state; | 122 | if (sbi->s_version != MINIX_V3) |
123 | ms->s_state = sbi->s_mount_state; | ||
121 | mark_buffer_dirty(sbi->s_sbh); | 124 | mark_buffer_dirty(sbi->s_sbh); |
122 | } else { | 125 | } else { |
123 | /* Mount a partition which is read-only, read-write. */ | 126 | /* Mount a partition which is read-only, read-write. */ |
124 | sbi->s_mount_state = ms->s_state; | 127 | if (sbi->s_version != MINIX_V3) { |
125 | ms->s_state &= ~MINIX_VALID_FS; | 128 | sbi->s_mount_state = ms->s_state; |
129 | ms->s_state &= ~MINIX_VALID_FS; | ||
130 | } else { | ||
131 | sbi->s_mount_state = MINIX_VALID_FS; | ||
132 | } | ||
126 | mark_buffer_dirty(sbi->s_sbh); | 133 | mark_buffer_dirty(sbi->s_sbh); |
127 | 134 | ||
128 | if (!(sbi->s_mount_state & MINIX_VALID_FS)) | 135 | if (!(sbi->s_mount_state & MINIX_VALID_FS)) |
@@ -140,7 +147,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) | |||
140 | struct buffer_head *bh; | 147 | struct buffer_head *bh; |
141 | struct buffer_head **map; | 148 | struct buffer_head **map; |
142 | struct minix_super_block *ms; | 149 | struct minix_super_block *ms; |
143 | int i, block; | 150 | struct minix3_super_block *m3s = NULL; |
151 | unsigned long i, block; | ||
144 | struct inode *root_inode; | 152 | struct inode *root_inode; |
145 | struct minix_sb_info *sbi; | 153 | struct minix_sb_info *sbi; |
146 | 154 | ||
@@ -192,6 +200,22 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) | |||
192 | sbi->s_dirsize = 32; | 200 | sbi->s_dirsize = 32; |
193 | sbi->s_namelen = 30; | 201 | sbi->s_namelen = 30; |
194 | sbi->s_link_max = MINIX2_LINK_MAX; | 202 | sbi->s_link_max = MINIX2_LINK_MAX; |
203 | } else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) { | ||
204 | m3s = (struct minix3_super_block *) bh->b_data; | ||
205 | s->s_magic = m3s->s_magic; | ||
206 | sbi->s_imap_blocks = m3s->s_imap_blocks; | ||
207 | sbi->s_zmap_blocks = m3s->s_zmap_blocks; | ||
208 | sbi->s_firstdatazone = m3s->s_firstdatazone; | ||
209 | sbi->s_log_zone_size = m3s->s_log_zone_size; | ||
210 | sbi->s_max_size = m3s->s_max_size; | ||
211 | sbi->s_ninodes = m3s->s_ninodes; | ||
212 | sbi->s_nzones = m3s->s_zones; | ||
213 | sbi->s_dirsize = 64; | ||
214 | sbi->s_namelen = 60; | ||
215 | sbi->s_version = MINIX_V3; | ||
216 | sbi->s_link_max = MINIX2_LINK_MAX; | ||
217 | sbi->s_mount_state = MINIX_VALID_FS; | ||
218 | sb_set_blocksize(s, m3s->s_blocksize); | ||
195 | } else | 219 | } else |
196 | goto out_no_fs; | 220 | goto out_no_fs; |
197 | 221 | ||
@@ -236,7 +260,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) | |||
236 | s->s_root->d_op = &minix_dentry_operations; | 260 | s->s_root->d_op = &minix_dentry_operations; |
237 | 261 | ||
238 | if (!(s->s_flags & MS_RDONLY)) { | 262 | if (!(s->s_flags & MS_RDONLY)) { |
239 | ms->s_state &= ~MINIX_VALID_FS; | 263 | if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ |
264 | ms->s_state &= ~MINIX_VALID_FS; | ||
240 | mark_buffer_dirty(bh); | 265 | mark_buffer_dirty(bh); |
241 | } | 266 | } |
242 | if (!(sbi->s_mount_state & MINIX_VALID_FS)) | 267 | if (!(sbi->s_mount_state & MINIX_VALID_FS)) |
@@ -278,8 +303,8 @@ out_illegal_sb: | |||
278 | 303 | ||
279 | out_no_fs: | 304 | out_no_fs: |
280 | if (!silent) | 305 | if (!silent) |
281 | printk("VFS: Can't find a Minix or Minix V2 filesystem " | 306 | printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 " |
282 | "on device %s\n", s->s_id); | 307 | "on device %s.\n", s->s_id); |
283 | out_release: | 308 | out_release: |
284 | brelse(bh); | 309 | brelse(bh); |
285 | goto out; | 310 | goto out; |
@@ -344,7 +369,7 @@ static const struct address_space_operations minix_aops = { | |||
344 | .bmap = minix_bmap | 369 | .bmap = minix_bmap |
345 | }; | 370 | }; |
346 | 371 | ||
347 | static struct inode_operations minix_symlink_inode_operations = { | 372 | static const struct inode_operations minix_symlink_inode_operations = { |
348 | .readlink = generic_readlink, | 373 | .readlink = generic_readlink, |
349 | .follow_link = page_follow_link_light, | 374 | .follow_link = page_follow_link_light, |
350 | .put_link = page_put_link, | 375 | .put_link = page_put_link, |
@@ -537,12 +562,14 @@ int minix_sync_inode(struct inode * inode) | |||
537 | 562 | ||
538 | int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 563 | int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
539 | { | 564 | { |
565 | struct inode *dir = dentry->d_parent->d_inode; | ||
566 | struct super_block *sb = dir->i_sb; | ||
540 | generic_fillattr(dentry->d_inode, stat); | 567 | generic_fillattr(dentry->d_inode, stat); |
541 | if (INODE_VERSION(dentry->d_inode) == MINIX_V1) | 568 | if (INODE_VERSION(dentry->d_inode) == MINIX_V1) |
542 | stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size); | 569 | stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb); |
543 | else | 570 | else |
544 | stat->blocks = (BLOCK_SIZE / 512) * V2_minix_blocks(stat->size); | 571 | stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb); |
545 | stat->blksize = BLOCK_SIZE; | 572 | stat->blksize = sb->s_blocksize; |
546 | return 0; | 573 | return 0; |
547 | } | 574 | } |
548 | 575 | ||
diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c index 429baf8de105..a731cabf1540 100644 --- a/fs/minix/itree_common.c +++ b/fs/minix/itree_common.c | |||
@@ -23,7 +23,7 @@ static inline int verify_chain(Indirect *from, Indirect *to) | |||
23 | 23 | ||
24 | static inline block_t *block_end(struct buffer_head *bh) | 24 | static inline block_t *block_end(struct buffer_head *bh) |
25 | { | 25 | { |
26 | return (block_t *)((char*)bh->b_data + BLOCK_SIZE); | 26 | return (block_t *)((char*)bh->b_data + bh->b_size); |
27 | } | 27 | } |
28 | 28 | ||
29 | static inline Indirect *get_branch(struct inode *inode, | 29 | static inline Indirect *get_branch(struct inode *inode, |
@@ -85,7 +85,7 @@ static int alloc_branch(struct inode *inode, | |||
85 | branch[n].key = cpu_to_block(nr); | 85 | branch[n].key = cpu_to_block(nr); |
86 | bh = sb_getblk(inode->i_sb, parent); | 86 | bh = sb_getblk(inode->i_sb, parent); |
87 | lock_buffer(bh); | 87 | lock_buffer(bh); |
88 | memset(bh->b_data, 0, BLOCK_SIZE); | 88 | memset(bh->b_data, 0, bh->b_size); |
89 | branch[n].bh = bh; | 89 | branch[n].bh = bh; |
90 | branch[n].p = (block_t*) bh->b_data + offsets[n]; | 90 | branch[n].p = (block_t*) bh->b_data + offsets[n]; |
91 | *branch[n].p = branch[n].key; | 91 | *branch[n].p = branch[n].key; |
@@ -292,6 +292,7 @@ static void free_branches(struct inode *inode, block_t *p, block_t *q, int depth | |||
292 | 292 | ||
293 | static inline void truncate (struct inode * inode) | 293 | static inline void truncate (struct inode * inode) |
294 | { | 294 | { |
295 | struct super_block *sb = inode->i_sb; | ||
295 | block_t *idata = i_data(inode); | 296 | block_t *idata = i_data(inode); |
296 | int offsets[DEPTH]; | 297 | int offsets[DEPTH]; |
297 | Indirect chain[DEPTH]; | 298 | Indirect chain[DEPTH]; |
@@ -301,7 +302,7 @@ static inline void truncate (struct inode * inode) | |||
301 | int first_whole; | 302 | int first_whole; |
302 | long iblock; | 303 | long iblock; |
303 | 304 | ||
304 | iblock = (inode->i_size + BLOCK_SIZE-1) >> 10; | 305 | iblock = (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits; |
305 | block_truncate_page(inode->i_mapping, inode->i_size, get_block); | 306 | block_truncate_page(inode->i_mapping, inode->i_size, get_block); |
306 | 307 | ||
307 | n = block_to_path(inode, iblock, offsets); | 308 | n = block_to_path(inode, iblock, offsets); |
@@ -346,15 +347,16 @@ do_indirects: | |||
346 | mark_inode_dirty(inode); | 347 | mark_inode_dirty(inode); |
347 | } | 348 | } |
348 | 349 | ||
349 | static inline unsigned nblocks(loff_t size) | 350 | static inline unsigned nblocks(loff_t size, struct super_block *sb) |
350 | { | 351 | { |
352 | int k = sb->s_blocksize_bits - 10; | ||
351 | unsigned blocks, res, direct = DIRECT, i = DEPTH; | 353 | unsigned blocks, res, direct = DIRECT, i = DEPTH; |
352 | blocks = (size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; | 354 | blocks = (size + sb->s_blocksize - 1) >> (BLOCK_SIZE_BITS + k); |
353 | res = blocks; | 355 | res = blocks; |
354 | while (--i && blocks > direct) { | 356 | while (--i && blocks > direct) { |
355 | blocks -= direct; | 357 | blocks -= direct; |
356 | blocks += BLOCK_SIZE/sizeof(block_t) - 1; | 358 | blocks += sb->s_blocksize/sizeof(block_t) - 1; |
357 | blocks /= BLOCK_SIZE/sizeof(block_t); | 359 | blocks /= sb->s_blocksize/sizeof(block_t); |
358 | res += blocks; | 360 | res += blocks; |
359 | direct = 1; | 361 | direct = 1; |
360 | } | 362 | } |
diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c index 656b1347a25b..1a5f3bf0bcec 100644 --- a/fs/minix/itree_v1.c +++ b/fs/minix/itree_v1.c | |||
@@ -55,7 +55,7 @@ void V1_minix_truncate(struct inode * inode) | |||
55 | truncate(inode); | 55 | truncate(inode); |
56 | } | 56 | } |
57 | 57 | ||
58 | unsigned V1_minix_blocks(loff_t size) | 58 | unsigned V1_minix_blocks(loff_t size, struct super_block *sb) |
59 | { | 59 | { |
60 | return nblocks(size); | 60 | return nblocks(size, sb); |
61 | } | 61 | } |
diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c index 9adcdc754e0f..ad8f0dec4ef4 100644 --- a/fs/minix/itree_v2.c +++ b/fs/minix/itree_v2.c | |||
@@ -23,10 +23,11 @@ static inline block_t *i_data(struct inode *inode) | |||
23 | static int block_to_path(struct inode * inode, long block, int offsets[DEPTH]) | 23 | static int block_to_path(struct inode * inode, long block, int offsets[DEPTH]) |
24 | { | 24 | { |
25 | int n = 0; | 25 | int n = 0; |
26 | struct super_block *sb = inode->i_sb; | ||
26 | 27 | ||
27 | if (block < 0) { | 28 | if (block < 0) { |
28 | printk("minix_bmap: block<0\n"); | 29 | printk("minix_bmap: block<0\n"); |
29 | } else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) { | 30 | } else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) { |
30 | printk("minix_bmap: block>big\n"); | 31 | printk("minix_bmap: block>big\n"); |
31 | } else if (block < 7) { | 32 | } else if (block < 7) { |
32 | offsets[n++] = block; | 33 | offsets[n++] = block; |
@@ -60,7 +61,7 @@ void V2_minix_truncate(struct inode * inode) | |||
60 | truncate(inode); | 61 | truncate(inode); |
61 | } | 62 | } |
62 | 63 | ||
63 | unsigned V2_minix_blocks(loff_t size) | 64 | unsigned V2_minix_blocks(loff_t size, struct super_block *sb) |
64 | { | 65 | { |
65 | return nblocks(size); | 66 | return nblocks(size, sb); |
66 | } | 67 | } |
diff --git a/fs/minix/minix.h b/fs/minix/minix.h index c55b77cdcc8e..73ef84f8fb0b 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h | |||
@@ -7,11 +7,10 @@ | |||
7 | * truncated. Else they will be disallowed (ENAMETOOLONG). | 7 | * truncated. Else they will be disallowed (ENAMETOOLONG). |
8 | */ | 8 | */ |
9 | #define NO_TRUNCATE 1 | 9 | #define NO_TRUNCATE 1 |
10 | |||
11 | #define INODE_VERSION(inode) minix_sb(inode->i_sb)->s_version | 10 | #define INODE_VERSION(inode) minix_sb(inode->i_sb)->s_version |
12 | |||
13 | #define MINIX_V1 0x0001 /* original minix fs */ | 11 | #define MINIX_V1 0x0001 /* original minix fs */ |
14 | #define MINIX_V2 0x0002 /* minix V2 fs */ | 12 | #define MINIX_V2 0x0002 /* minix V2 fs */ |
13 | #define MINIX_V3 0x0003 /* minix V3 fs */ | ||
15 | 14 | ||
16 | /* | 15 | /* |
17 | * minix fs inode data in memory | 16 | * minix fs inode data in memory |
@@ -52,12 +51,10 @@ extern struct inode * minix_new_inode(const struct inode * dir, int * error); | |||
52 | extern void minix_free_inode(struct inode * inode); | 51 | extern void minix_free_inode(struct inode * inode); |
53 | extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi); | 52 | extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi); |
54 | extern int minix_new_block(struct inode * inode); | 53 | extern int minix_new_block(struct inode * inode); |
55 | extern void minix_free_block(struct inode * inode, int block); | 54 | extern void minix_free_block(struct inode *inode, unsigned long block); |
56 | extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi); | 55 | extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi); |
57 | |||
58 | extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 56 | extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
59 | 57 | ||
60 | extern void V2_minix_truncate(struct inode *); | ||
61 | extern void V1_minix_truncate(struct inode *); | 58 | extern void V1_minix_truncate(struct inode *); |
62 | extern void V2_minix_truncate(struct inode *); | 59 | extern void V2_minix_truncate(struct inode *); |
63 | extern void minix_truncate(struct inode *); | 60 | extern void minix_truncate(struct inode *); |
@@ -65,8 +62,8 @@ extern int minix_sync_inode(struct inode *); | |||
65 | extern void minix_set_inode(struct inode *, dev_t); | 62 | extern void minix_set_inode(struct inode *, dev_t); |
66 | extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int); | 63 | extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int); |
67 | extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int); | 64 | extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int); |
68 | extern unsigned V1_minix_blocks(loff_t); | 65 | extern unsigned V1_minix_blocks(loff_t, struct super_block *); |
69 | extern unsigned V2_minix_blocks(loff_t); | 66 | extern unsigned V2_minix_blocks(loff_t, struct super_block *); |
70 | 67 | ||
71 | extern struct minix_dir_entry *minix_find_entry(struct dentry*, struct page**); | 68 | extern struct minix_dir_entry *minix_find_entry(struct dentry*, struct page**); |
72 | extern int minix_add_link(struct dentry*, struct inode*); | 69 | extern int minix_add_link(struct dentry*, struct inode*); |
@@ -76,11 +73,10 @@ extern int minix_empty_dir(struct inode*); | |||
76 | extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*); | 73 | extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*); |
77 | extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**); | 74 | extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**); |
78 | extern ino_t minix_inode_by_name(struct dentry*); | 75 | extern ino_t minix_inode_by_name(struct dentry*); |
79 | |||
80 | extern int minix_sync_file(struct file *, struct dentry *, int); | 76 | extern int minix_sync_file(struct file *, struct dentry *, int); |
81 | 77 | ||
82 | extern struct inode_operations minix_file_inode_operations; | 78 | extern const struct inode_operations minix_file_inode_operations; |
83 | extern struct inode_operations minix_dir_inode_operations; | 79 | extern const struct inode_operations minix_dir_inode_operations; |
84 | extern const struct file_operations minix_file_operations; | 80 | extern const struct file_operations minix_file_operations; |
85 | extern const struct file_operations minix_dir_operations; | 81 | extern const struct file_operations minix_dir_operations; |
86 | extern struct dentry_operations minix_dentry_operations; | 82 | extern struct dentry_operations minix_dentry_operations; |
diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 299bb66e3bde..f4aa7a939040 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c | |||
@@ -291,7 +291,7 @@ out: | |||
291 | /* | 291 | /* |
292 | * directories can handle most operations... | 292 | * directories can handle most operations... |
293 | */ | 293 | */ |
294 | struct inode_operations minix_dir_inode_operations = { | 294 | const struct inode_operations minix_dir_inode_operations = { |
295 | .create = minix_create, | 295 | .create = minix_create, |
296 | .lookup = minix_lookup, | 296 | .lookup = minix_lookup, |
297 | .link = minix_link, | 297 | .link = minix_link, |
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 452461955cbd..30f7d0ae2215 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c | |||
@@ -646,7 +646,7 @@ out: | |||
646 | return err; | 646 | return err; |
647 | } | 647 | } |
648 | 648 | ||
649 | static struct inode_operations msdos_dir_inode_operations = { | 649 | static const struct inode_operations msdos_dir_inode_operations = { |
650 | .create = msdos_create, | 650 | .create = msdos_create, |
651 | .lookup = msdos_lookup, | 651 | .lookup = msdos_lookup, |
652 | .unlink = msdos_unlink, | 652 | .unlink = msdos_unlink, |
diff --git a/fs/namei.c b/fs/namei.c index e4f108f08230..ee60cc4d3453 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2688,10 +2688,11 @@ int __page_symlink(struct inode *inode, const char *symname, int len, | |||
2688 | { | 2688 | { |
2689 | struct address_space *mapping = inode->i_mapping; | 2689 | struct address_space *mapping = inode->i_mapping; |
2690 | struct page *page; | 2690 | struct page *page; |
2691 | int err = -ENOMEM; | 2691 | int err; |
2692 | char *kaddr; | 2692 | char *kaddr; |
2693 | 2693 | ||
2694 | retry: | 2694 | retry: |
2695 | err = -ENOMEM; | ||
2695 | page = find_or_create_page(mapping, 0, gfp_mask); | 2696 | page = find_or_create_page(mapping, 0, gfp_mask); |
2696 | if (!page) | 2697 | if (!page) |
2697 | goto fail; | 2698 | goto fail; |
@@ -2744,7 +2745,7 @@ int page_symlink(struct inode *inode, const char *symname, int len) | |||
2744 | mapping_gfp_mask(inode->i_mapping)); | 2745 | mapping_gfp_mask(inode->i_mapping)); |
2745 | } | 2746 | } |
2746 | 2747 | ||
2747 | struct inode_operations page_symlink_inode_operations = { | 2748 | const struct inode_operations page_symlink_inode_operations = { |
2748 | .readlink = generic_readlink, | 2749 | .readlink = generic_readlink, |
2749 | .follow_link = page_follow_link_light, | 2750 | .follow_link = page_follow_link_light, |
2750 | .put_link = page_put_link, | 2751 | .put_link = page_put_link, |
diff --git a/fs/namespace.c b/fs/namespace.c index 5ef336c1103c..fd999cab7b57 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -53,9 +53,8 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) | |||
53 | 53 | ||
54 | struct vfsmount *alloc_vfsmnt(const char *name) | 54 | struct vfsmount *alloc_vfsmnt(const char *name) |
55 | { | 55 | { |
56 | struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); | 56 | struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); |
57 | if (mnt) { | 57 | if (mnt) { |
58 | memset(mnt, 0, sizeof(struct vfsmount)); | ||
59 | atomic_set(&mnt->mnt_count, 1); | 58 | atomic_set(&mnt->mnt_count, 1); |
60 | INIT_LIST_HEAD(&mnt->mnt_hash); | 59 | INIT_LIST_HEAD(&mnt->mnt_hash); |
61 | INIT_LIST_HEAD(&mnt->mnt_child); | 60 | INIT_LIST_HEAD(&mnt->mnt_child); |
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 73747772c3bb..011ef0b6d2d4 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
@@ -58,7 +58,7 @@ const struct file_operations ncp_dir_operations = | |||
58 | #endif | 58 | #endif |
59 | }; | 59 | }; |
60 | 60 | ||
61 | struct inode_operations ncp_dir_inode_operations = | 61 | const struct inode_operations ncp_dir_inode_operations = |
62 | { | 62 | { |
63 | .create = ncp_create, | 63 | .create = ncp_create, |
64 | .lookup = ncp_lookup, | 64 | .lookup = ncp_lookup, |
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index b91fea03b1c3..6b1f6d27099a 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c | |||
@@ -297,7 +297,7 @@ const struct file_operations ncp_file_operations = | |||
297 | .fsync = ncp_fsync, | 297 | .fsync = ncp_fsync, |
298 | }; | 298 | }; |
299 | 299 | ||
300 | struct inode_operations ncp_file_inode_operations = | 300 | const struct inode_operations ncp_file_inode_operations = |
301 | { | 301 | { |
302 | .setattr = ncp_notify_change, | 302 | .setattr = ncp_notify_change, |
303 | }; | 303 | }; |
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 67a90bf795d5..14939ddf74f1 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
@@ -90,7 +90,7 @@ static int ncp_remount(struct super_block *sb, int *flags, char* data) | |||
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
93 | static struct super_operations ncp_sops = | 93 | static const struct super_operations ncp_sops = |
94 | { | 94 | { |
95 | .alloc_inode = ncp_alloc_inode, | 95 | .alloc_inode = ncp_alloc_inode, |
96 | .destroy_inode = ncp_destroy_inode, | 96 | .destroy_inode = ncp_destroy_inode, |
@@ -229,7 +229,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) | |||
229 | } | 229 | } |
230 | 230 | ||
231 | #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) | 231 | #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) |
232 | static struct inode_operations ncp_symlink_inode_operations = { | 232 | static const struct inode_operations ncp_symlink_inode_operations = { |
233 | .readlink = generic_readlink, | 233 | .readlink = generic_readlink, |
234 | .follow_link = page_follow_link_light, | 234 | .follow_link = page_follow_link_light, |
235 | .put_link = page_put_link, | 235 | .put_link = page_put_link, |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 7933e2e99dbc..75f309c8741a 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -71,6 +71,8 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
71 | complete(&nfs_callback_info.started); | 71 | complete(&nfs_callback_info.started); |
72 | 72 | ||
73 | for(;;) { | 73 | for(;;) { |
74 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
75 | |||
74 | if (signalled()) { | 76 | if (signalled()) { |
75 | if (nfs_callback_info.users == 0) | 77 | if (nfs_callback_info.users == 0) |
76 | break; | 78 | break; |
@@ -88,8 +90,8 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
88 | __FUNCTION__, -err); | 90 | __FUNCTION__, -err); |
89 | break; | 91 | break; |
90 | } | 92 | } |
91 | dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__, | 93 | dprintk("%s: request from %s\n", __FUNCTION__, |
92 | NIPQUAD(rqstp->rq_addr.sin_addr.s_addr)); | 94 | svc_print_addr(rqstp, buf, sizeof(buf))); |
93 | svc_process(rqstp); | 95 | svc_process(rqstp); |
94 | } | 96 | } |
95 | 97 | ||
@@ -106,7 +108,6 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
106 | int nfs_callback_up(void) | 108 | int nfs_callback_up(void) |
107 | { | 109 | { |
108 | struct svc_serv *serv; | 110 | struct svc_serv *serv; |
109 | struct svc_sock *svsk; | ||
110 | int ret = 0; | 111 | int ret = 0; |
111 | 112 | ||
112 | lock_kernel(); | 113 | lock_kernel(); |
@@ -119,17 +120,14 @@ int nfs_callback_up(void) | |||
119 | ret = -ENOMEM; | 120 | ret = -ENOMEM; |
120 | if (!serv) | 121 | if (!serv) |
121 | goto out_err; | 122 | goto out_err; |
122 | /* FIXME: We don't want to register this socket with the portmapper */ | 123 | |
123 | ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport); | 124 | ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport, |
124 | if (ret < 0) | 125 | SVC_SOCK_ANONYMOUS); |
126 | if (ret <= 0) | ||
125 | goto out_destroy; | 127 | goto out_destroy; |
126 | if (!list_empty(&serv->sv_permsocks)) { | 128 | nfs_callback_tcpport = ret; |
127 | svsk = list_entry(serv->sv_permsocks.next, | 129 | dprintk("Callback port = 0x%x\n", nfs_callback_tcpport); |
128 | struct svc_sock, sk_list); | 130 | |
129 | nfs_callback_tcpport = ntohs(inet_sk(svsk->sk_sk)->sport); | ||
130 | dprintk ("Callback port = 0x%x\n", nfs_callback_tcpport); | ||
131 | } else | ||
132 | BUG(); | ||
133 | ret = svc_create_thread(nfs_callback_svc, serv); | 131 | ret = svc_create_thread(nfs_callback_svc, serv); |
134 | if (ret < 0) | 132 | if (ret < 0) |
135 | goto out_destroy; | 133 | goto out_destroy; |
@@ -140,6 +138,8 @@ out: | |||
140 | unlock_kernel(); | 138 | unlock_kernel(); |
141 | return ret; | 139 | return ret; |
142 | out_destroy: | 140 | out_destroy: |
141 | dprintk("Couldn't create callback socket or server thread; err = %d\n", | ||
142 | ret); | ||
143 | svc_destroy(serv); | 143 | svc_destroy(serv); |
144 | out_err: | 144 | out_err: |
145 | nfs_callback_info.users--; | 145 | nfs_callback_info.users--; |
@@ -166,15 +166,19 @@ void nfs_callback_down(void) | |||
166 | 166 | ||
167 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) | 167 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) |
168 | { | 168 | { |
169 | struct sockaddr_in *addr = &rqstp->rq_addr; | 169 | struct sockaddr_in *addr = svc_addr_in(rqstp); |
170 | struct nfs_client *clp; | 170 | struct nfs_client *clp; |
171 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
171 | 172 | ||
172 | /* Don't talk to strangers */ | 173 | /* Don't talk to strangers */ |
173 | clp = nfs_find_client(addr, 4); | 174 | clp = nfs_find_client(addr, 4); |
174 | if (clp == NULL) | 175 | if (clp == NULL) |
175 | return SVC_DROP; | 176 | return SVC_DROP; |
176 | dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr)); | 177 | |
178 | dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__, | ||
179 | svc_print_addr(rqstp, buf, sizeof(buf))); | ||
177 | nfs_put_client(clp); | 180 | nfs_put_client(clp); |
181 | |||
178 | switch (rqstp->rq_authop->flavour) { | 182 | switch (rqstp->rq_authop->flavour) { |
179 | case RPC_AUTH_NULL: | 183 | case RPC_AUTH_NULL: |
180 | if (rqstp->rq_proc != CB_NULL) | 184 | if (rqstp->rq_proc != CB_NULL) |
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index f8ea1f51f590..849a2029975d 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -176,7 +176,7 @@ static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr | |||
176 | status = decode_fh(xdr, &args->fh); | 176 | status = decode_fh(xdr, &args->fh); |
177 | if (unlikely(status != 0)) | 177 | if (unlikely(status != 0)) |
178 | goto out; | 178 | goto out; |
179 | args->addr = &rqstp->rq_addr; | 179 | args->addr = svc_addr_in(rqstp); |
180 | status = decode_bitmap(xdr, args->bitmap); | 180 | status = decode_bitmap(xdr, args->bitmap); |
181 | out: | 181 | out: |
182 | dprintk("%s: exit with status = %d\n", __FUNCTION__, status); | 182 | dprintk("%s: exit with status = %d\n", __FUNCTION__, status); |
@@ -188,7 +188,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, | |||
188 | __be32 *p; | 188 | __be32 *p; |
189 | __be32 status; | 189 | __be32 status; |
190 | 190 | ||
191 | args->addr = &rqstp->rq_addr; | 191 | args->addr = svc_addr_in(rqstp); |
192 | status = decode_stateid(xdr, &args->stateid); | 192 | status = decode_stateid(xdr, &args->stateid); |
193 | if (unlikely(status != 0)) | 193 | if (unlikely(status != 0)) |
194 | goto out; | 194 | goto out; |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 23ab145daa2d..2190e6c2792e 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -394,7 +394,8 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | |||
394 | static int nfs_create_rpc_client(struct nfs_client *clp, int proto, | 394 | static int nfs_create_rpc_client(struct nfs_client *clp, int proto, |
395 | unsigned int timeo, | 395 | unsigned int timeo, |
396 | unsigned int retrans, | 396 | unsigned int retrans, |
397 | rpc_authflavor_t flavor) | 397 | rpc_authflavor_t flavor, |
398 | int flags) | ||
398 | { | 399 | { |
399 | struct rpc_timeout timeparms; | 400 | struct rpc_timeout timeparms; |
400 | struct rpc_clnt *clnt = NULL; | 401 | struct rpc_clnt *clnt = NULL; |
@@ -407,6 +408,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto, | |||
407 | .program = &nfs_program, | 408 | .program = &nfs_program, |
408 | .version = clp->rpc_ops->version, | 409 | .version = clp->rpc_ops->version, |
409 | .authflavor = flavor, | 410 | .authflavor = flavor, |
411 | .flags = flags, | ||
410 | }; | 412 | }; |
411 | 413 | ||
412 | if (!IS_ERR(clp->cl_rpcclient)) | 414 | if (!IS_ERR(clp->cl_rpcclient)) |
@@ -548,7 +550,7 @@ static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data * | |||
548 | * - RFC 2623, sec 2.3.2 | 550 | * - RFC 2623, sec 2.3.2 |
549 | */ | 551 | */ |
550 | error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans, | 552 | error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans, |
551 | RPC_AUTH_UNIX); | 553 | RPC_AUTH_UNIX, 0); |
552 | if (error < 0) | 554 | if (error < 0) |
553 | goto error; | 555 | goto error; |
554 | nfs_mark_client_ready(clp, NFS_CS_READY); | 556 | nfs_mark_client_ready(clp, NFS_CS_READY); |
@@ -868,7 +870,8 @@ static int nfs4_init_client(struct nfs_client *clp, | |||
868 | /* Check NFS protocol revision and initialize RPC op vector */ | 870 | /* Check NFS protocol revision and initialize RPC op vector */ |
869 | clp->rpc_ops = &nfs_v4_clientops; | 871 | clp->rpc_ops = &nfs_v4_clientops; |
870 | 872 | ||
871 | error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour); | 873 | error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour, |
874 | RPC_CLNT_CREATE_DISCRTRY); | ||
872 | if (error < 0) | 875 | if (error < 0) |
873 | goto error; | 876 | goto error; |
874 | memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); | 877 | memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); |
@@ -1030,7 +1033,7 @@ error: | |||
1030 | * Create an NFS4 referral server record | 1033 | * Create an NFS4 referral server record |
1031 | */ | 1034 | */ |
1032 | struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | 1035 | struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, |
1033 | struct nfs_fh *fh) | 1036 | struct nfs_fh *mntfh) |
1034 | { | 1037 | { |
1035 | struct nfs_client *parent_client; | 1038 | struct nfs_client *parent_client; |
1036 | struct nfs_server *server, *parent_server; | 1039 | struct nfs_server *server, *parent_server; |
@@ -1069,8 +1072,13 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1069 | BUG_ON(!server->nfs_client->rpc_ops); | 1072 | BUG_ON(!server->nfs_client->rpc_ops); |
1070 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 1073 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
1071 | 1074 | ||
1075 | /* Probe the root fh to retrieve its FSID and filehandle */ | ||
1076 | error = nfs4_path_walk(server, mntfh, data->mnt_path); | ||
1077 | if (error < 0) | ||
1078 | goto error; | ||
1079 | |||
1072 | /* probe the filesystem info for this server filesystem */ | 1080 | /* probe the filesystem info for this server filesystem */ |
1073 | error = nfs_probe_fsinfo(server, fh, &fattr); | 1081 | error = nfs_probe_fsinfo(server, mntfh, &fattr); |
1074 | if (error < 0) | 1082 | if (error < 0) |
1075 | goto error; | 1083 | goto error; |
1076 | 1084 | ||
@@ -1173,7 +1181,7 @@ static struct seq_operations nfs_server_list_ops = { | |||
1173 | .show = nfs_server_list_show, | 1181 | .show = nfs_server_list_show, |
1174 | }; | 1182 | }; |
1175 | 1183 | ||
1176 | static struct file_operations nfs_server_list_fops = { | 1184 | static const struct file_operations nfs_server_list_fops = { |
1177 | .open = nfs_server_list_open, | 1185 | .open = nfs_server_list_open, |
1178 | .read = seq_read, | 1186 | .read = seq_read, |
1179 | .llseek = seq_lseek, | 1187 | .llseek = seq_lseek, |
@@ -1193,7 +1201,7 @@ static struct seq_operations nfs_volume_list_ops = { | |||
1193 | .show = nfs_volume_list_show, | 1201 | .show = nfs_volume_list_show, |
1194 | }; | 1202 | }; |
1195 | 1203 | ||
1196 | static struct file_operations nfs_volume_list_fops = { | 1204 | static const struct file_operations nfs_volume_list_fops = { |
1197 | .open = nfs_volume_list_open, | 1205 | .open = nfs_volume_list_open, |
1198 | .read = seq_read, | 1206 | .read = seq_read, |
1199 | .llseek = seq_lseek, | 1207 | .llseek = seq_lseek, |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index d9ba8cb0ee75..92d8ec859e22 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -65,7 +65,7 @@ const struct file_operations nfs_dir_operations = { | |||
65 | .fsync = nfs_fsync_dir, | 65 | .fsync = nfs_fsync_dir, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct inode_operations nfs_dir_inode_operations = { | 68 | const struct inode_operations nfs_dir_inode_operations = { |
69 | .create = nfs_create, | 69 | .create = nfs_create, |
70 | .lookup = nfs_lookup, | 70 | .lookup = nfs_lookup, |
71 | .link = nfs_link, | 71 | .link = nfs_link, |
@@ -81,7 +81,7 @@ struct inode_operations nfs_dir_inode_operations = { | |||
81 | }; | 81 | }; |
82 | 82 | ||
83 | #ifdef CONFIG_NFS_V3 | 83 | #ifdef CONFIG_NFS_V3 |
84 | struct inode_operations nfs3_dir_inode_operations = { | 84 | const struct inode_operations nfs3_dir_inode_operations = { |
85 | .create = nfs_create, | 85 | .create = nfs_create, |
86 | .lookup = nfs_lookup, | 86 | .lookup = nfs_lookup, |
87 | .link = nfs_link, | 87 | .link = nfs_link, |
@@ -104,7 +104,7 @@ struct inode_operations nfs3_dir_inode_operations = { | |||
104 | #ifdef CONFIG_NFS_V4 | 104 | #ifdef CONFIG_NFS_V4 |
105 | 105 | ||
106 | static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); | 106 | static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); |
107 | struct inode_operations nfs4_dir_inode_operations = { | 107 | const struct inode_operations nfs4_dir_inode_operations = { |
108 | .create = nfs_create, | 108 | .create = nfs_create, |
109 | .lookup = nfs_atomic_lookup, | 109 | .lookup = nfs_atomic_lookup, |
110 | .link = nfs_link, | 110 | .link = nfs_link, |
@@ -637,7 +637,7 @@ int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) | |||
637 | * In the case it has, we assume that the dentries are untrustworthy | 637 | * In the case it has, we assume that the dentries are untrustworthy |
638 | * and may need to be looked up again. | 638 | * and may need to be looked up again. |
639 | */ | 639 | */ |
640 | static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | 640 | static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) |
641 | { | 641 | { |
642 | if (IS_ROOT(dentry)) | 642 | if (IS_ROOT(dentry)) |
643 | return 1; | 643 | return 1; |
@@ -652,6 +652,12 @@ static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) | |||
652 | dentry->d_fsdata = (void *)verf; | 652 | dentry->d_fsdata = (void *)verf; |
653 | } | 653 | } |
654 | 654 | ||
655 | static void nfs_refresh_verifier(struct dentry * dentry, unsigned long verf) | ||
656 | { | ||
657 | if (time_after(verf, (unsigned long)dentry->d_fsdata)) | ||
658 | nfs_set_verifier(dentry, verf); | ||
659 | } | ||
660 | |||
655 | /* | 661 | /* |
656 | * Whenever an NFS operation succeeds, we know that the dentry | 662 | * Whenever an NFS operation succeeds, we know that the dentry |
657 | * is valid, so we update the revalidation timestamp. | 663 | * is valid, so we update the revalidation timestamp. |
@@ -785,7 +791,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
785 | goto out_bad; | 791 | goto out_bad; |
786 | 792 | ||
787 | nfs_renew_times(dentry); | 793 | nfs_renew_times(dentry); |
788 | nfs_set_verifier(dentry, verifier); | 794 | nfs_refresh_verifier(dentry, verifier); |
789 | out_valid: | 795 | out_valid: |
790 | unlock_kernel(); | 796 | unlock_kernel(); |
791 | dput(parent); | 797 | dput(parent); |
@@ -1085,7 +1091,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1085 | verifier = nfs_save_change_attribute(dir); | 1091 | verifier = nfs_save_change_attribute(dir); |
1086 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); | 1092 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); |
1087 | if (!ret) | 1093 | if (!ret) |
1088 | nfs_set_verifier(dentry, verifier); | 1094 | nfs_refresh_verifier(dentry, verifier); |
1089 | unlock_kernel(); | 1095 | unlock_kernel(); |
1090 | out: | 1096 | out: |
1091 | dput(parent); | 1097 | dput(parent); |
@@ -1123,8 +1129,21 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
1123 | } | 1129 | } |
1124 | name.hash = full_name_hash(name.name, name.len); | 1130 | name.hash = full_name_hash(name.name, name.len); |
1125 | dentry = d_lookup(parent, &name); | 1131 | dentry = d_lookup(parent, &name); |
1126 | if (dentry != NULL) | 1132 | if (dentry != NULL) { |
1127 | return dentry; | 1133 | /* Is this a positive dentry that matches the readdir info? */ |
1134 | if (dentry->d_inode != NULL && | ||
1135 | (NFS_FILEID(dentry->d_inode) == entry->ino || | ||
1136 | d_mountpoint(dentry))) { | ||
1137 | if (!desc->plus || entry->fh->size == 0) | ||
1138 | return dentry; | ||
1139 | if (nfs_compare_fh(NFS_FH(dentry->d_inode), | ||
1140 | entry->fh) == 0) | ||
1141 | goto out_renew; | ||
1142 | } | ||
1143 | /* No, so d_drop to allow one to be created */ | ||
1144 | d_drop(dentry); | ||
1145 | dput(dentry); | ||
1146 | } | ||
1128 | if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) | 1147 | if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) |
1129 | return NULL; | 1148 | return NULL; |
1130 | /* Note: caller is already holding the dir->i_mutex! */ | 1149 | /* Note: caller is already holding the dir->i_mutex! */ |
@@ -1149,6 +1168,10 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
1149 | nfs_renew_times(dentry); | 1168 | nfs_renew_times(dentry); |
1150 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1169 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1151 | return dentry; | 1170 | return dentry; |
1171 | out_renew: | ||
1172 | nfs_renew_times(dentry); | ||
1173 | nfs_refresh_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1174 | return dentry; | ||
1152 | } | 1175 | } |
1153 | 1176 | ||
1154 | /* | 1177 | /* |
@@ -1443,6 +1466,8 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1443 | if (atomic_read(&dentry->d_count) > 1) { | 1466 | if (atomic_read(&dentry->d_count) > 1) { |
1444 | spin_unlock(&dentry->d_lock); | 1467 | spin_unlock(&dentry->d_lock); |
1445 | spin_unlock(&dcache_lock); | 1468 | spin_unlock(&dcache_lock); |
1469 | /* Start asynchronous writeout of the inode */ | ||
1470 | write_inode_now(dentry->d_inode, 0); | ||
1446 | error = nfs_sillyrename(dir, dentry); | 1471 | error = nfs_sillyrename(dir, dentry); |
1447 | unlock_kernel(); | 1472 | unlock_kernel(); |
1448 | return error; | 1473 | return error; |
@@ -1684,7 +1709,7 @@ out: | |||
1684 | if (!error) { | 1709 | if (!error) { |
1685 | d_move(old_dentry, new_dentry); | 1710 | d_move(old_dentry, new_dentry); |
1686 | nfs_renew_times(new_dentry); | 1711 | nfs_renew_times(new_dentry); |
1687 | nfs_set_verifier(new_dentry, nfs_save_change_attribute(new_dir)); | 1712 | nfs_refresh_verifier(new_dentry, nfs_save_change_attribute(new_dir)); |
1688 | } | 1713 | } |
1689 | 1714 | ||
1690 | /* new dentry created? */ | 1715 | /* new dentry created? */ |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index bd21d7fde650..b1c98ea39b72 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -309,7 +309,8 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo | |||
309 | 309 | ||
310 | rpc_execute(&data->task); | 310 | rpc_execute(&data->task); |
311 | 311 | ||
312 | dfprintk(VFS, "NFS: %5u initiated direct read call (req %s/%Ld, %zu bytes @ offset %Lu)\n", | 312 | dprintk("NFS: %5u initiated direct read call " |
313 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | ||
313 | data->task.tk_pid, | 314 | data->task.tk_pid, |
314 | inode->i_sb->s_id, | 315 | inode->i_sb->s_id, |
315 | (long long)NFS_FILEID(inode), | 316 | (long long)NFS_FILEID(inode), |
@@ -639,7 +640,8 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l | |||
639 | 640 | ||
640 | rpc_execute(&data->task); | 641 | rpc_execute(&data->task); |
641 | 642 | ||
642 | dfprintk(VFS, "NFS: %5u initiated direct write call (req %s/%Ld, %zu bytes @ offset %Lu)\n", | 643 | dprintk("NFS: %5u initiated direct write call " |
644 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | ||
643 | data->task.tk_pid, | 645 | data->task.tk_pid, |
644 | inode->i_sb->s_id, | 646 | inode->i_sb->s_id, |
645 | (long long)NFS_FILEID(inode), | 647 | (long long)NFS_FILEID(inode), |
@@ -797,7 +799,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
797 | const char __user *buf = iov[0].iov_base; | 799 | const char __user *buf = iov[0].iov_base; |
798 | size_t count = iov[0].iov_len; | 800 | size_t count = iov[0].iov_len; |
799 | 801 | ||
800 | dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n", | 802 | dprintk("nfs: direct write(%s/%s, %lu@%Ld)\n", |
801 | file->f_path.dentry->d_parent->d_name.name, | 803 | file->f_path.dentry->d_parent->d_name.name, |
802 | file->f_path.dentry->d_name.name, | 804 | file->f_path.dentry->d_name.name, |
803 | (unsigned long) count, (long long) pos); | 805 | (unsigned long) count, (long long) pos); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 9e4a2b70995a..8e66b5a2d490 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -68,14 +68,14 @@ const struct file_operations nfs_file_operations = { | |||
68 | .check_flags = nfs_check_flags, | 68 | .check_flags = nfs_check_flags, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | struct inode_operations nfs_file_inode_operations = { | 71 | const struct inode_operations nfs_file_inode_operations = { |
72 | .permission = nfs_permission, | 72 | .permission = nfs_permission, |
73 | .getattr = nfs_getattr, | 73 | .getattr = nfs_getattr, |
74 | .setattr = nfs_setattr, | 74 | .setattr = nfs_setattr, |
75 | }; | 75 | }; |
76 | 76 | ||
77 | #ifdef CONFIG_NFS_V3 | 77 | #ifdef CONFIG_NFS_V3 |
78 | struct inode_operations nfs3_file_inode_operations = { | 78 | const struct inode_operations nfs3_file_inode_operations = { |
79 | .permission = nfs_permission, | 79 | .permission = nfs_permission, |
80 | .getattr = nfs_getattr, | 80 | .getattr = nfs_getattr, |
81 | .setattr = nfs_setattr, | 81 | .setattr = nfs_setattr, |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 8391bd7a83ce..6ef268f7c300 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -135,17 +135,15 @@ int nfs4_path_walk(struct nfs_server *server, | |||
135 | struct nfs_fh lastfh; | 135 | struct nfs_fh lastfh; |
136 | struct qstr name; | 136 | struct qstr name; |
137 | int ret; | 137 | int ret; |
138 | //int referral_count = 0; | ||
139 | 138 | ||
140 | dprintk("--> nfs4_path_walk(,,%s)\n", path); | 139 | dprintk("--> nfs4_path_walk(,,%s)\n", path); |
141 | 140 | ||
142 | fsinfo.fattr = &fattr; | 141 | fsinfo.fattr = &fattr; |
143 | nfs_fattr_init(&fattr); | 142 | nfs_fattr_init(&fattr); |
144 | 143 | ||
145 | if (*path++ != '/') { | 144 | /* Eat leading slashes */ |
146 | dprintk("nfs4_get_root: Path does not begin with a slash\n"); | 145 | while (*path == '/') |
147 | return -EINVAL; | 146 | path++; |
148 | } | ||
149 | 147 | ||
150 | /* Start by getting the root filehandle from the server */ | 148 | /* Start by getting the root filehandle from the server */ |
151 | ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); | 149 | ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); |
@@ -160,6 +158,7 @@ int nfs4_path_walk(struct nfs_server *server, | |||
160 | return -ENOTDIR; | 158 | return -ENOTDIR; |
161 | } | 159 | } |
162 | 160 | ||
161 | /* FIXME: It is quite valid for the server to return a referral here */ | ||
163 | if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { | 162 | if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { |
164 | printk(KERN_ERR "nfs4_get_root:" | 163 | printk(KERN_ERR "nfs4_get_root:" |
165 | " getroot obtained referral\n"); | 164 | " getroot obtained referral\n"); |
@@ -187,6 +186,7 @@ eat_dot_dir: | |||
187 | goto eat_dot_dir; | 186 | goto eat_dot_dir; |
188 | } | 187 | } |
189 | 188 | ||
189 | /* FIXME: Why shouldn't the user be able to use ".." in the path? */ | ||
190 | if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2]) | 190 | if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2]) |
191 | ) { | 191 | ) { |
192 | printk(KERN_ERR "nfs4_get_root:" | 192 | printk(KERN_ERR "nfs4_get_root:" |
@@ -212,6 +212,7 @@ eat_dot_dir: | |||
212 | return -ENOTDIR; | 212 | return -ENOTDIR; |
213 | } | 213 | } |
214 | 214 | ||
215 | /* FIXME: Referrals are quite valid here too */ | ||
215 | if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { | 216 | if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { |
216 | printk(KERN_ERR "nfs4_get_root:" | 217 | printk(KERN_ERR "nfs4_get_root:" |
217 | " lookupfh obtained referral\n"); | 218 | " lookupfh obtained referral\n"); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index d83498282837..af53c02f473b 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -65,13 +65,18 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) | |||
65 | 65 | ||
66 | int nfs_write_inode(struct inode *inode, int sync) | 66 | int nfs_write_inode(struct inode *inode, int sync) |
67 | { | 67 | { |
68 | int flags = sync ? FLUSH_SYNC : 0; | ||
69 | int ret; | 68 | int ret; |
70 | 69 | ||
71 | ret = nfs_commit_inode(inode, flags); | 70 | if (sync) { |
72 | if (ret < 0) | 71 | ret = filemap_fdatawait(inode->i_mapping); |
73 | return ret; | 72 | if (ret == 0) |
74 | return 0; | 73 | ret = nfs_commit_inode(inode, FLUSH_SYNC); |
74 | } else | ||
75 | ret = nfs_commit_inode(inode, 0); | ||
76 | if (ret >= 0) | ||
77 | return 0; | ||
78 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | ||
79 | return ret; | ||
75 | } | 80 | } |
76 | 81 | ||
77 | void nfs_clear_inode(struct inode *inode) | 82 | void nfs_clear_inode(struct inode *inode) |
@@ -235,6 +240,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
235 | 240 | ||
236 | if (inode->i_state & I_NEW) { | 241 | if (inode->i_state & I_NEW) { |
237 | struct nfs_inode *nfsi = NFS_I(inode); | 242 | struct nfs_inode *nfsi = NFS_I(inode); |
243 | unsigned long now = jiffies; | ||
238 | 244 | ||
239 | /* We set i_ino for the few things that still rely on it, | 245 | /* We set i_ino for the few things that still rely on it, |
240 | * such as stat(2) */ | 246 | * such as stat(2) */ |
@@ -271,7 +277,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
271 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 277 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
272 | 278 | ||
273 | nfsi->read_cache_jiffies = fattr->time_start; | 279 | nfsi->read_cache_jiffies = fattr->time_start; |
274 | nfsi->last_updated = jiffies; | 280 | nfsi->last_updated = now; |
281 | nfsi->cache_change_attribute = now; | ||
275 | inode->i_atime = fattr->atime; | 282 | inode->i_atime = fattr->atime; |
276 | inode->i_mtime = fattr->mtime; | 283 | inode->i_mtime = fattr->mtime; |
277 | inode->i_ctime = fattr->ctime; | 284 | inode->i_ctime = fattr->ctime; |
@@ -290,7 +297,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
290 | inode->i_blocks = fattr->du.nfs2.blocks; | 297 | inode->i_blocks = fattr->du.nfs2.blocks; |
291 | } | 298 | } |
292 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 299 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
293 | nfsi->attrtimeo_timestamp = jiffies; | 300 | nfsi->attrtimeo_timestamp = now; |
294 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 301 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
295 | nfsi->access_cache = RB_ROOT; | 302 | nfsi->access_cache = RB_ROOT; |
296 | 303 | ||
@@ -783,20 +790,21 @@ void nfs_end_data_update(struct inode *inode) | |||
783 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 790 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
784 | { | 791 | { |
785 | struct nfs_inode *nfsi = NFS_I(inode); | 792 | struct nfs_inode *nfsi = NFS_I(inode); |
793 | unsigned long now = jiffies; | ||
786 | 794 | ||
787 | /* If we have atomic WCC data, we may update some attributes */ | 795 | /* If we have atomic WCC data, we may update some attributes */ |
788 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { | 796 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { |
789 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { | 797 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { |
790 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 798 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
791 | nfsi->cache_change_attribute = jiffies; | 799 | nfsi->cache_change_attribute = now; |
792 | } | 800 | } |
793 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 801 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { |
794 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 802 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
795 | nfsi->cache_change_attribute = jiffies; | 803 | nfsi->cache_change_attribute = now; |
796 | } | 804 | } |
797 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) { | 805 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) { |
798 | inode->i_size = fattr->size; | 806 | inode->i_size = fattr->size; |
799 | nfsi->cache_change_attribute = jiffies; | 807 | nfsi->cache_change_attribute = now; |
800 | } | 808 | } |
801 | } | 809 | } |
802 | } | 810 | } |
@@ -934,6 +942,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
934 | struct nfs_inode *nfsi = NFS_I(inode); | 942 | struct nfs_inode *nfsi = NFS_I(inode); |
935 | loff_t cur_isize, new_isize; | 943 | loff_t cur_isize, new_isize; |
936 | unsigned int invalid = 0; | 944 | unsigned int invalid = 0; |
945 | unsigned long now = jiffies; | ||
937 | int data_stable; | 946 | int data_stable; |
938 | 947 | ||
939 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", | 948 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", |
@@ -959,7 +968,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
959 | * Update the read time so we don't revalidate too often. | 968 | * Update the read time so we don't revalidate too often. |
960 | */ | 969 | */ |
961 | nfsi->read_cache_jiffies = fattr->time_start; | 970 | nfsi->read_cache_jiffies = fattr->time_start; |
962 | nfsi->last_updated = jiffies; | 971 | nfsi->last_updated = now; |
972 | |||
973 | /* Fix a wraparound issue with nfsi->cache_change_attribute */ | ||
974 | if (time_before(now, nfsi->cache_change_attribute)) | ||
975 | nfsi->cache_change_attribute = now - 600*HZ; | ||
963 | 976 | ||
964 | /* Are we racing with known updates of the metadata on the server? */ | 977 | /* Are we racing with known updates of the metadata on the server? */ |
965 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); | 978 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); |
@@ -985,7 +998,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
985 | inode->i_size = new_isize; | 998 | inode->i_size = new_isize; |
986 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 999 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
987 | } | 1000 | } |
988 | nfsi->cache_change_attribute = jiffies; | 1001 | nfsi->cache_change_attribute = now; |
989 | dprintk("NFS: isize change on server for file %s/%ld\n", | 1002 | dprintk("NFS: isize change on server for file %s/%ld\n", |
990 | inode->i_sb->s_id, inode->i_ino); | 1003 | inode->i_sb->s_id, inode->i_ino); |
991 | } | 1004 | } |
@@ -996,14 +1009,14 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
996 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1009 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
997 | inode->i_sb->s_id, inode->i_ino); | 1010 | inode->i_sb->s_id, inode->i_ino); |
998 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1011 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
999 | nfsi->cache_change_attribute = jiffies; | 1012 | nfsi->cache_change_attribute = now; |
1000 | } | 1013 | } |
1001 | 1014 | ||
1002 | /* If ctime has changed we should definitely clear access+acl caches */ | 1015 | /* If ctime has changed we should definitely clear access+acl caches */ |
1003 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1016 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
1004 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1017 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1005 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1018 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
1006 | nfsi->cache_change_attribute = jiffies; | 1019 | nfsi->cache_change_attribute = now; |
1007 | } | 1020 | } |
1008 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | 1021 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
1009 | 1022 | ||
@@ -1032,18 +1045,18 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1032 | inode->i_sb->s_id, inode->i_ino); | 1045 | inode->i_sb->s_id, inode->i_ino); |
1033 | nfsi->change_attr = fattr->change_attr; | 1046 | nfsi->change_attr = fattr->change_attr; |
1034 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1047 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1035 | nfsi->cache_change_attribute = jiffies; | 1048 | nfsi->cache_change_attribute = now; |
1036 | } | 1049 | } |
1037 | 1050 | ||
1038 | /* Update attrtimeo value if we're out of the unstable period */ | 1051 | /* Update attrtimeo value if we're out of the unstable period */ |
1039 | if (invalid & NFS_INO_INVALID_ATTR) { | 1052 | if (invalid & NFS_INO_INVALID_ATTR) { |
1040 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1053 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1041 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1054 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1042 | nfsi->attrtimeo_timestamp = jiffies; | 1055 | nfsi->attrtimeo_timestamp = now; |
1043 | } else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { | 1056 | } else if (time_after(now, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { |
1044 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) | 1057 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) |
1045 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1058 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); |
1046 | nfsi->attrtimeo_timestamp = jiffies; | 1059 | nfsi->attrtimeo_timestamp = now; |
1047 | } | 1060 | } |
1048 | /* Don't invalidate the data if we were to blame */ | 1061 | /* Don't invalidate the data if we were to blame */ |
1049 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1062 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
@@ -1122,7 +1135,6 @@ struct inode *nfs_alloc_inode(struct super_block *sb) | |||
1122 | return NULL; | 1135 | return NULL; |
1123 | nfsi->flags = 0UL; | 1136 | nfsi->flags = 0UL; |
1124 | nfsi->cache_validity = 0UL; | 1137 | nfsi->cache_validity = 0UL; |
1125 | nfsi->cache_change_attribute = jiffies; | ||
1126 | #ifdef CONFIG_NFS_V3_ACL | 1138 | #ifdef CONFIG_NFS_V3_ACL |
1127 | nfsi->acl_access = ERR_PTR(-EAGAIN); | 1139 | nfsi->acl_access = ERR_PTR(-EAGAIN); |
1128 | nfsi->acl_default = ERR_PTR(-EAGAIN); | 1140 | nfsi->acl_default = ERR_PTR(-EAGAIN); |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index a28f6ce2e131..6610f2b02077 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -107,10 +107,6 @@ extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus); | |||
107 | /* nfs4proc.c */ | 107 | /* nfs4proc.c */ |
108 | #ifdef CONFIG_NFS_V4 | 108 | #ifdef CONFIG_NFS_V4 |
109 | extern struct rpc_procinfo nfs4_procedures[]; | 109 | extern struct rpc_procinfo nfs4_procedures[]; |
110 | |||
111 | extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, | ||
112 | struct nfs4_fs_locations *fs_locations, | ||
113 | struct page *page); | ||
114 | #endif | 110 | #endif |
115 | 111 | ||
116 | /* dir.c */ | 112 | /* dir.c */ |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 371b804e7cc8..7f86e65182e4 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -155,12 +155,12 @@ out_follow: | |||
155 | goto out; | 155 | goto out; |
156 | } | 156 | } |
157 | 157 | ||
158 | struct inode_operations nfs_mountpoint_inode_operations = { | 158 | const struct inode_operations nfs_mountpoint_inode_operations = { |
159 | .follow_link = nfs_follow_mountpoint, | 159 | .follow_link = nfs_follow_mountpoint, |
160 | .getattr = nfs_getattr, | 160 | .getattr = nfs_getattr, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | struct inode_operations nfs_referral_inode_operations = { | 163 | const struct inode_operations nfs_referral_inode_operations = { |
164 | .follow_link = nfs_follow_mountpoint, | 164 | .follow_link = nfs_follow_mountpoint, |
165 | }; | 165 | }; |
166 | 166 | ||
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index acd8fe9762d3..7d0371e2bad5 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -253,29 +253,6 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page, | |||
253 | return status; | 253 | return status; |
254 | } | 254 | } |
255 | 255 | ||
256 | static int nfs3_proc_read(struct nfs_read_data *rdata) | ||
257 | { | ||
258 | int flags = rdata->flags; | ||
259 | struct inode * inode = rdata->inode; | ||
260 | struct nfs_fattr * fattr = rdata->res.fattr; | ||
261 | struct rpc_message msg = { | ||
262 | .rpc_proc = &nfs3_procedures[NFS3PROC_READ], | ||
263 | .rpc_argp = &rdata->args, | ||
264 | .rpc_resp = &rdata->res, | ||
265 | .rpc_cred = rdata->cred, | ||
266 | }; | ||
267 | int status; | ||
268 | |||
269 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, | ||
270 | (long long) rdata->args.offset); | ||
271 | nfs_fattr_init(fattr); | ||
272 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); | ||
273 | if (status >= 0) | ||
274 | nfs_refresh_inode(inode, fattr); | ||
275 | dprintk("NFS reply read: %d\n", status); | ||
276 | return status; | ||
277 | } | ||
278 | |||
279 | /* | 256 | /* |
280 | * Create a regular file. | 257 | * Create a regular file. |
281 | * For now, we don't implement O_EXCL. | 258 | * For now, we don't implement O_EXCL. |
@@ -855,7 +832,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = { | |||
855 | .lookup = nfs3_proc_lookup, | 832 | .lookup = nfs3_proc_lookup, |
856 | .access = nfs3_proc_access, | 833 | .access = nfs3_proc_access, |
857 | .readlink = nfs3_proc_readlink, | 834 | .readlink = nfs3_proc_readlink, |
858 | .read = nfs3_proc_read, | ||
859 | .create = nfs3_proc_create, | 835 | .create = nfs3_proc_create, |
860 | .remove = nfs3_proc_remove, | 836 | .remove = nfs3_proc_remove, |
861 | .unlink_setup = nfs3_proc_unlink_setup, | 837 | .unlink_setup = nfs3_proc_unlink_setup, |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index c26cd978c7cc..cf3a17eb5c09 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -151,7 +151,7 @@ struct nfs4_state_recovery_ops { | |||
151 | }; | 151 | }; |
152 | 152 | ||
153 | extern struct dentry_operations nfs4_dentry_operations; | 153 | extern struct dentry_operations nfs4_dentry_operations; |
154 | extern struct inode_operations nfs4_dir_inode_operations; | 154 | extern const struct inode_operations nfs4_dir_inode_operations; |
155 | 155 | ||
156 | /* inode.c */ | 156 | /* inode.c */ |
157 | extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t); | 157 | extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t); |
@@ -169,7 +169,7 @@ extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state); | |||
169 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); | 169 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); |
170 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); | 170 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); |
171 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); | 171 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); |
172 | extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, | 172 | extern int nfs4_proc_fs_locations(struct inode *dir, struct qstr *name, |
173 | struct nfs4_fs_locations *fs_locations, struct page *page); | 173 | struct nfs4_fs_locations *fs_locations, struct page *page); |
174 | 174 | ||
175 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; | 175 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index b872779d7cd5..dd5fef20c702 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/vfs.h> | 16 | #include <linux/vfs.h> |
17 | #include <linux/inet.h> | 17 | #include <linux/inet.h> |
18 | #include "internal.h" | 18 | #include "internal.h" |
19 | #include "nfs4_fs.h" | ||
19 | 20 | ||
20 | #define NFSDBG_FACILITY NFSDBG_VFS | 21 | #define NFSDBG_FACILITY NFSDBG_VFS |
21 | 22 | ||
@@ -130,7 +131,6 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
130 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, | 131 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, |
131 | }; | 132 | }; |
132 | char *page = NULL, *page2 = NULL; | 133 | char *page = NULL, *page2 = NULL; |
133 | char *devname; | ||
134 | int loc, s, error; | 134 | int loc, s, error; |
135 | 135 | ||
136 | if (locations == NULL || locations->nlocations <= 0) | 136 | if (locations == NULL || locations->nlocations <= 0) |
@@ -154,12 +154,6 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
154 | goto out; | 154 | goto out; |
155 | } | 155 | } |
156 | 156 | ||
157 | devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE); | ||
158 | if (IS_ERR(devname)) { | ||
159 | mnt = (struct vfsmount *)devname; | ||
160 | goto out; | ||
161 | } | ||
162 | |||
163 | loc = 0; | 157 | loc = 0; |
164 | while (loc < locations->nlocations && IS_ERR(mnt)) { | 158 | while (loc < locations->nlocations && IS_ERR(mnt)) { |
165 | const struct nfs4_fs_location *location = &locations->locations[loc]; | 159 | const struct nfs4_fs_location *location = &locations->locations[loc]; |
@@ -194,7 +188,11 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
194 | addr.sin_port = htons(NFS_PORT); | 188 | addr.sin_port = htons(NFS_PORT); |
195 | mountdata.addr = &addr; | 189 | mountdata.addr = &addr; |
196 | 190 | ||
197 | mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, devname, &mountdata); | 191 | snprintf(page, PAGE_SIZE, "%s:%s", |
192 | mountdata.hostname, | ||
193 | mountdata.mnt_path); | ||
194 | |||
195 | mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, &mountdata); | ||
198 | if (!IS_ERR(mnt)) { | 196 | if (!IS_ERR(mnt)) { |
199 | break; | 197 | break; |
200 | } | 198 | } |
@@ -242,7 +240,7 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr | |||
242 | dprintk("%s: getting locations for %s/%s\n", | 240 | dprintk("%s: getting locations for %s/%s\n", |
243 | __FUNCTION__, parent->d_name.name, dentry->d_name.name); | 241 | __FUNCTION__, parent->d_name.name, dentry->d_name.name); |
244 | 242 | ||
245 | err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page); | 243 | err = nfs4_proc_fs_locations(parent->d_inode, &dentry->d_name, fs_locations, page); |
246 | dput(parent); | 244 | dput(parent); |
247 | if (err != 0 || | 245 | if (err != 0 || |
248 | fs_locations->nlocations <= 0 || | 246 | fs_locations->nlocations <= 0 || |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index b3fd29baadc3..f52cf5c33c6c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1140,7 +1140,6 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
1140 | break; | 1140 | break; |
1141 | case -NFS4ERR_STALE_STATEID: | 1141 | case -NFS4ERR_STALE_STATEID: |
1142 | case -NFS4ERR_EXPIRED: | 1142 | case -NFS4ERR_EXPIRED: |
1143 | nfs4_schedule_state_recovery(server->nfs_client); | ||
1144 | break; | 1143 | break; |
1145 | default: | 1144 | default: |
1146 | if (nfs4_async_handle_error(task, server) == -EAGAIN) { | 1145 | if (nfs4_async_handle_error(task, server) == -EAGAIN) { |
@@ -1424,7 +1423,6 @@ static int nfs4_get_referral(struct inode *dir, struct qstr *name, struct nfs_fa | |||
1424 | int status = -ENOMEM; | 1423 | int status = -ENOMEM; |
1425 | struct page *page = NULL; | 1424 | struct page *page = NULL; |
1426 | struct nfs4_fs_locations *locations = NULL; | 1425 | struct nfs4_fs_locations *locations = NULL; |
1427 | struct dentry dentry = {}; | ||
1428 | 1426 | ||
1429 | page = alloc_page(GFP_KERNEL); | 1427 | page = alloc_page(GFP_KERNEL); |
1430 | if (page == NULL) | 1428 | if (page == NULL) |
@@ -1433,9 +1431,7 @@ static int nfs4_get_referral(struct inode *dir, struct qstr *name, struct nfs_fa | |||
1433 | if (locations == NULL) | 1431 | if (locations == NULL) |
1434 | goto out; | 1432 | goto out; |
1435 | 1433 | ||
1436 | dentry.d_name.name = name->name; | 1434 | status = nfs4_proc_fs_locations(dir, name, locations, page); |
1437 | dentry.d_name.len = name->len; | ||
1438 | status = nfs4_proc_fs_locations(dir, &dentry, locations, page); | ||
1439 | if (status != 0) | 1435 | if (status != 0) |
1440 | goto out; | 1436 | goto out; |
1441 | /* Make sure server returned a different fsid for the referral */ | 1437 | /* Make sure server returned a different fsid for the referral */ |
@@ -1737,44 +1733,6 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page, | |||
1737 | return err; | 1733 | return err; |
1738 | } | 1734 | } |
1739 | 1735 | ||
1740 | static int _nfs4_proc_read(struct nfs_read_data *rdata) | ||
1741 | { | ||
1742 | int flags = rdata->flags; | ||
1743 | struct inode *inode = rdata->inode; | ||
1744 | struct nfs_fattr *fattr = rdata->res.fattr; | ||
1745 | struct nfs_server *server = NFS_SERVER(inode); | ||
1746 | struct rpc_message msg = { | ||
1747 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ], | ||
1748 | .rpc_argp = &rdata->args, | ||
1749 | .rpc_resp = &rdata->res, | ||
1750 | .rpc_cred = rdata->cred, | ||
1751 | }; | ||
1752 | unsigned long timestamp = jiffies; | ||
1753 | int status; | ||
1754 | |||
1755 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, | ||
1756 | (long long) rdata->args.offset); | ||
1757 | |||
1758 | nfs_fattr_init(fattr); | ||
1759 | status = rpc_call_sync(server->client, &msg, flags); | ||
1760 | if (!status) | ||
1761 | renew_lease(server, timestamp); | ||
1762 | dprintk("NFS reply read: %d\n", status); | ||
1763 | return status; | ||
1764 | } | ||
1765 | |||
1766 | static int nfs4_proc_read(struct nfs_read_data *rdata) | ||
1767 | { | ||
1768 | struct nfs4_exception exception = { }; | ||
1769 | int err; | ||
1770 | do { | ||
1771 | err = nfs4_handle_exception(NFS_SERVER(rdata->inode), | ||
1772 | _nfs4_proc_read(rdata), | ||
1773 | &exception); | ||
1774 | } while (exception.retry); | ||
1775 | return err; | ||
1776 | } | ||
1777 | |||
1778 | /* | 1736 | /* |
1779 | * Got race? | 1737 | * Got race? |
1780 | * We will need to arrange for the VFS layer to provide an atomic open. | 1738 | * We will need to arrange for the VFS layer to provide an atomic open. |
@@ -2753,11 +2711,15 @@ static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp) | |||
2753 | 2711 | ||
2754 | might_sleep(); | 2712 | might_sleep(); |
2755 | 2713 | ||
2714 | rwsem_acquire(&clp->cl_sem.dep_map, 0, 0, _RET_IP_); | ||
2715 | |||
2756 | rpc_clnt_sigmask(clnt, &oldset); | 2716 | rpc_clnt_sigmask(clnt, &oldset); |
2757 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER, | 2717 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER, |
2758 | nfs4_wait_bit_interruptible, | 2718 | nfs4_wait_bit_interruptible, |
2759 | TASK_INTERRUPTIBLE); | 2719 | TASK_INTERRUPTIBLE); |
2760 | rpc_clnt_sigunmask(clnt, &oldset); | 2720 | rpc_clnt_sigunmask(clnt, &oldset); |
2721 | |||
2722 | rwsem_release(&clp->cl_sem.dep_map, 1, _RET_IP_); | ||
2761 | return res; | 2723 | return res; |
2762 | } | 2724 | } |
2763 | 2725 | ||
@@ -2996,7 +2958,6 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 | |||
2996 | switch (err) { | 2958 | switch (err) { |
2997 | case -NFS4ERR_STALE_STATEID: | 2959 | case -NFS4ERR_STALE_STATEID: |
2998 | case -NFS4ERR_EXPIRED: | 2960 | case -NFS4ERR_EXPIRED: |
2999 | nfs4_schedule_state_recovery(server->nfs_client); | ||
3000 | case 0: | 2961 | case 0: |
3001 | return 0; | 2962 | return 0; |
3002 | } | 2963 | } |
@@ -3150,12 +3111,10 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
3150 | break; | 3111 | break; |
3151 | case -NFS4ERR_STALE_STATEID: | 3112 | case -NFS4ERR_STALE_STATEID: |
3152 | case -NFS4ERR_EXPIRED: | 3113 | case -NFS4ERR_EXPIRED: |
3153 | nfs4_schedule_state_recovery(calldata->server->nfs_client); | ||
3154 | break; | 3114 | break; |
3155 | default: | 3115 | default: |
3156 | if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN) { | 3116 | if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN) |
3157 | rpc_restart_call(task); | 3117 | rpc_restart_call(task); |
3158 | } | ||
3159 | } | 3118 | } |
3160 | } | 3119 | } |
3161 | 3120 | ||
@@ -3585,7 +3544,7 @@ ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen) | |||
3585 | return len; | 3544 | return len; |
3586 | } | 3545 | } |
3587 | 3546 | ||
3588 | int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, | 3547 | int nfs4_proc_fs_locations(struct inode *dir, struct qstr *name, |
3589 | struct nfs4_fs_locations *fs_locations, struct page *page) | 3548 | struct nfs4_fs_locations *fs_locations, struct page *page) |
3590 | { | 3549 | { |
3591 | struct nfs_server *server = NFS_SERVER(dir); | 3550 | struct nfs_server *server = NFS_SERVER(dir); |
@@ -3595,7 +3554,7 @@ int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, | |||
3595 | }; | 3554 | }; |
3596 | struct nfs4_fs_locations_arg args = { | 3555 | struct nfs4_fs_locations_arg args = { |
3597 | .dir_fh = NFS_FH(dir), | 3556 | .dir_fh = NFS_FH(dir), |
3598 | .name = &dentry->d_name, | 3557 | .name = name, |
3599 | .page = page, | 3558 | .page = page, |
3600 | .bitmask = bitmask, | 3559 | .bitmask = bitmask, |
3601 | }; | 3560 | }; |
@@ -3607,7 +3566,7 @@ int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, | |||
3607 | int status; | 3566 | int status; |
3608 | 3567 | ||
3609 | dprintk("%s: start\n", __FUNCTION__); | 3568 | dprintk("%s: start\n", __FUNCTION__); |
3610 | fs_locations->fattr.valid = 0; | 3569 | nfs_fattr_init(&fs_locations->fattr); |
3611 | fs_locations->server = server; | 3570 | fs_locations->server = server; |
3612 | fs_locations->nlocations = 0; | 3571 | fs_locations->nlocations = 0; |
3613 | status = rpc_call_sync(server->client, &msg, 0); | 3572 | status = rpc_call_sync(server->client, &msg, 0); |
@@ -3625,7 +3584,7 @@ struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = { | |||
3625 | .recover_lock = nfs4_lock_expired, | 3584 | .recover_lock = nfs4_lock_expired, |
3626 | }; | 3585 | }; |
3627 | 3586 | ||
3628 | static struct inode_operations nfs4_file_inode_operations = { | 3587 | static const struct inode_operations nfs4_file_inode_operations = { |
3629 | .permission = nfs_permission, | 3588 | .permission = nfs_permission, |
3630 | .getattr = nfs_getattr, | 3589 | .getattr = nfs_getattr, |
3631 | .setattr = nfs_setattr, | 3590 | .setattr = nfs_setattr, |
@@ -3646,7 +3605,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
3646 | .lookup = nfs4_proc_lookup, | 3605 | .lookup = nfs4_proc_lookup, |
3647 | .access = nfs4_proc_access, | 3606 | .access = nfs4_proc_access, |
3648 | .readlink = nfs4_proc_readlink, | 3607 | .readlink = nfs4_proc_readlink, |
3649 | .read = nfs4_proc_read, | ||
3650 | .create = nfs4_proc_create, | 3608 | .create = nfs4_proc_create, |
3651 | .remove = nfs4_proc_remove, | 3609 | .remove = nfs4_proc_remove, |
3652 | .unlink_setup = nfs4_proc_unlink_setup, | 3610 | .unlink_setup = nfs4_proc_unlink_setup, |
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c index 823298561c0a..f5f4430fb2a4 100644 --- a/fs/nfs/nfs4renewd.c +++ b/fs/nfs/nfs4renewd.c | |||
@@ -43,7 +43,6 @@ | |||
43 | * child task framework of the RPC layer? | 43 | * child task framework of the RPC layer? |
44 | */ | 44 | */ |
45 | 45 | ||
46 | #include <linux/sched.h> | ||
47 | #include <linux/smp_lock.h> | 46 | #include <linux/smp_lock.h> |
48 | #include <linux/mm.h> | 47 | #include <linux/mm.h> |
49 | #include <linux/pagemap.h> | 48 | #include <linux/pagemap.h> |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 0cf3fa312a33..f02d522fd788 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -387,8 +387,10 @@ static int nfs4_stat_to_errno(int); | |||
387 | decode_putfh_maxsz + \ | 387 | decode_putfh_maxsz + \ |
388 | op_decode_hdr_maxsz + 12) | 388 | op_decode_hdr_maxsz + 12) |
389 | #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ | 389 | #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ |
390 | encode_putfh_maxsz + \ | ||
390 | encode_getattr_maxsz) | 391 | encode_getattr_maxsz) |
391 | #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ | 392 | #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ |
393 | decode_putfh_maxsz + \ | ||
392 | decode_getattr_maxsz) | 394 | decode_getattr_maxsz) |
393 | #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ | 395 | #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ |
394 | encode_putfh_maxsz + \ | 396 | encode_putfh_maxsz + \ |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 560536ad74a4..1dcf56de9482 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -186,35 +186,6 @@ static int nfs_proc_readlink(struct inode *inode, struct page *page, | |||
186 | return status; | 186 | return status; |
187 | } | 187 | } |
188 | 188 | ||
189 | static int nfs_proc_read(struct nfs_read_data *rdata) | ||
190 | { | ||
191 | int flags = rdata->flags; | ||
192 | struct inode * inode = rdata->inode; | ||
193 | struct nfs_fattr * fattr = rdata->res.fattr; | ||
194 | struct rpc_message msg = { | ||
195 | .rpc_proc = &nfs_procedures[NFSPROC_READ], | ||
196 | .rpc_argp = &rdata->args, | ||
197 | .rpc_resp = &rdata->res, | ||
198 | .rpc_cred = rdata->cred, | ||
199 | }; | ||
200 | int status; | ||
201 | |||
202 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, | ||
203 | (long long) rdata->args.offset); | ||
204 | nfs_fattr_init(fattr); | ||
205 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); | ||
206 | if (status >= 0) { | ||
207 | nfs_refresh_inode(inode, fattr); | ||
208 | /* Emulate the eof flag, which isn't normally needed in NFSv2 | ||
209 | * as it is guaranteed to always return the file attributes | ||
210 | */ | ||
211 | if (rdata->args.offset + rdata->args.count >= fattr->size) | ||
212 | rdata->res.eof = 1; | ||
213 | } | ||
214 | dprintk("NFS reply read: %d\n", status); | ||
215 | return status; | ||
216 | } | ||
217 | |||
218 | static int | 189 | static int |
219 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 190 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
220 | int flags, struct nameidata *nd) | 191 | int flags, struct nameidata *nd) |
@@ -666,7 +637,6 @@ const struct nfs_rpc_ops nfs_v2_clientops = { | |||
666 | .lookup = nfs_proc_lookup, | 637 | .lookup = nfs_proc_lookup, |
667 | .access = NULL, /* access */ | 638 | .access = NULL, /* access */ |
668 | .readlink = nfs_proc_readlink, | 639 | .readlink = nfs_proc_readlink, |
669 | .read = nfs_proc_read, | ||
670 | .create = nfs_proc_create, | 640 | .create = nfs_proc_create, |
671 | .remove = nfs_proc_remove, | 641 | .remove = nfs_proc_remove, |
672 | .unlink_setup = nfs_proc_unlink_setup, | 642 | .unlink_setup = nfs_proc_unlink_setup, |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index a9c26521a9e2..6ab4d5a9edf2 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -5,14 +5,6 @@ | |||
5 | * | 5 | * |
6 | * Partial copy of Linus' read cache modifications to fs/nfs/file.c | 6 | * Partial copy of Linus' read cache modifications to fs/nfs/file.c |
7 | * modified for async RPC by okir@monad.swb.de | 7 | * modified for async RPC by okir@monad.swb.de |
8 | * | ||
9 | * We do an ugly hack here in order to return proper error codes to the | ||
10 | * user program when a read request failed: since generic_file_read | ||
11 | * only checks the return value of inode->i_op->readpage() which is always 0 | ||
12 | * for async RPC, we set the error bit of the page to 1 when an error occurs, | ||
13 | * and make nfs_readpage transmit requests synchronously when encountering this. | ||
14 | * This is only a small problem, though, since we now retry all operations | ||
15 | * within the RPC code when root squashing is suspected. | ||
16 | */ | 8 | */ |
17 | 9 | ||
18 | #include <linux/time.h> | 10 | #include <linux/time.h> |
@@ -122,93 +114,6 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data) | |||
122 | } | 114 | } |
123 | } | 115 | } |
124 | 116 | ||
125 | /* | ||
126 | * Read a page synchronously. | ||
127 | */ | ||
128 | static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode, | ||
129 | struct page *page) | ||
130 | { | ||
131 | unsigned int rsize = NFS_SERVER(inode)->rsize; | ||
132 | unsigned int count = PAGE_CACHE_SIZE; | ||
133 | int result = -ENOMEM; | ||
134 | struct nfs_read_data *rdata; | ||
135 | |||
136 | rdata = nfs_readdata_alloc(count); | ||
137 | if (!rdata) | ||
138 | goto out_unlock; | ||
139 | |||
140 | memset(rdata, 0, sizeof(*rdata)); | ||
141 | rdata->flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); | ||
142 | rdata->cred = ctx->cred; | ||
143 | rdata->inode = inode; | ||
144 | INIT_LIST_HEAD(&rdata->pages); | ||
145 | rdata->args.fh = NFS_FH(inode); | ||
146 | rdata->args.context = ctx; | ||
147 | rdata->args.pages = &page; | ||
148 | rdata->args.pgbase = 0UL; | ||
149 | rdata->args.count = rsize; | ||
150 | rdata->res.fattr = &rdata->fattr; | ||
151 | |||
152 | dprintk("NFS: nfs_readpage_sync(%p)\n", page); | ||
153 | |||
154 | /* | ||
155 | * This works now because the socket layer never tries to DMA | ||
156 | * into this buffer directly. | ||
157 | */ | ||
158 | do { | ||
159 | if (count < rsize) | ||
160 | rdata->args.count = count; | ||
161 | rdata->res.count = rdata->args.count; | ||
162 | rdata->args.offset = page_offset(page) + rdata->args.pgbase; | ||
163 | |||
164 | dprintk("NFS: nfs_proc_read(%s, (%s/%Ld), %Lu, %u)\n", | ||
165 | NFS_SERVER(inode)->nfs_client->cl_hostname, | ||
166 | inode->i_sb->s_id, | ||
167 | (long long)NFS_FILEID(inode), | ||
168 | (unsigned long long)rdata->args.pgbase, | ||
169 | rdata->args.count); | ||
170 | |||
171 | lock_kernel(); | ||
172 | result = NFS_PROTO(inode)->read(rdata); | ||
173 | unlock_kernel(); | ||
174 | |||
175 | /* | ||
176 | * Even if we had a partial success we can't mark the page | ||
177 | * cache valid. | ||
178 | */ | ||
179 | if (result < 0) { | ||
180 | if (result == -EISDIR) | ||
181 | result = -EINVAL; | ||
182 | goto io_error; | ||
183 | } | ||
184 | count -= result; | ||
185 | rdata->args.pgbase += result; | ||
186 | nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, result); | ||
187 | |||
188 | /* Note: result == 0 should only happen if we're caching | ||
189 | * a write that extends the file and punches a hole. | ||
190 | */ | ||
191 | if (rdata->res.eof != 0 || result == 0) | ||
192 | break; | ||
193 | } while (count); | ||
194 | spin_lock(&inode->i_lock); | ||
195 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
196 | spin_unlock(&inode->i_lock); | ||
197 | |||
198 | if (rdata->res.eof || rdata->res.count == rdata->args.count) { | ||
199 | SetPageUptodate(page); | ||
200 | if (rdata->res.eof && count != 0) | ||
201 | memclear_highpage_flush(page, rdata->args.pgbase, count); | ||
202 | } | ||
203 | result = 0; | ||
204 | |||
205 | io_error: | ||
206 | nfs_readdata_free(rdata); | ||
207 | out_unlock: | ||
208 | unlock_page(page); | ||
209 | return result; | ||
210 | } | ||
211 | |||
212 | static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | 117 | static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, |
213 | struct page *page) | 118 | struct page *page) |
214 | { | 119 | { |
@@ -278,7 +183,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
278 | 183 | ||
279 | data->task.tk_cookie = (unsigned long)inode; | 184 | data->task.tk_cookie = (unsigned long)inode; |
280 | 185 | ||
281 | dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n", | 186 | dprintk("NFS: %5u initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n", |
282 | data->task.tk_pid, | 187 | data->task.tk_pid, |
283 | inode->i_sb->s_id, | 188 | inode->i_sb->s_id, |
284 | (long long)NFS_FILEID(inode), | 189 | (long long)NFS_FILEID(inode), |
@@ -452,7 +357,7 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) | |||
452 | { | 357 | { |
453 | int status; | 358 | int status; |
454 | 359 | ||
455 | dprintk("%s: %4d, (status %d)\n", __FUNCTION__, task->tk_pid, | 360 | dprintk("NFS: %s: %5u, (status %d)\n", __FUNCTION__, task->tk_pid, |
456 | task->tk_status); | 361 | task->tk_status); |
457 | 362 | ||
458 | status = NFS_PROTO(data->inode)->read_done(task, data); | 363 | status = NFS_PROTO(data->inode)->read_done(task, data); |
@@ -621,15 +526,9 @@ int nfs_readpage(struct file *file, struct page *page) | |||
621 | } else | 526 | } else |
622 | ctx = get_nfs_open_context((struct nfs_open_context *) | 527 | ctx = get_nfs_open_context((struct nfs_open_context *) |
623 | file->private_data); | 528 | file->private_data); |
624 | if (!IS_SYNC(inode)) { | ||
625 | error = nfs_readpage_async(ctx, inode, page); | ||
626 | goto out; | ||
627 | } | ||
628 | 529 | ||
629 | error = nfs_readpage_sync(ctx, inode, page); | 530 | error = nfs_readpage_async(ctx, inode, page); |
630 | if (error < 0 && IS_SWAPFILE(inode)) | 531 | |
631 | printk("Aiee.. nfs swap-in of page failed!\n"); | ||
632 | out: | ||
633 | put_nfs_open_context(ctx); | 532 | put_nfs_open_context(ctx); |
634 | return error; | 533 | return error; |
635 | 534 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 28108c82b887..bb516a2cfbaf 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/vfs.h> | 44 | #include <linux/vfs.h> |
45 | #include <linux/inet.h> | 45 | #include <linux/inet.h> |
46 | #include <linux/nfs_xdr.h> | 46 | #include <linux/nfs_xdr.h> |
47 | #include <linux/magic.h> | ||
47 | 48 | ||
48 | #include <asm/system.h> | 49 | #include <asm/system.h> |
49 | #include <asm/uaccess.h> | 50 | #include <asm/uaccess.h> |
@@ -81,7 +82,7 @@ struct file_system_type nfs_xdev_fs_type = { | |||
81 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 82 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
82 | }; | 83 | }; |
83 | 84 | ||
84 | static struct super_operations nfs_sops = { | 85 | static const struct super_operations nfs_sops = { |
85 | .alloc_inode = nfs_alloc_inode, | 86 | .alloc_inode = nfs_alloc_inode, |
86 | .destroy_inode = nfs_destroy_inode, | 87 | .destroy_inode = nfs_destroy_inode, |
87 | .write_inode = nfs_write_inode, | 88 | .write_inode = nfs_write_inode, |
@@ -125,7 +126,7 @@ struct file_system_type nfs4_referral_fs_type = { | |||
125 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 126 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
126 | }; | 127 | }; |
127 | 128 | ||
128 | static struct super_operations nfs4_sops = { | 129 | static const struct super_operations nfs4_sops = { |
129 | .alloc_inode = nfs_alloc_inode, | 130 | .alloc_inode = nfs_alloc_inode, |
130 | .destroy_inode = nfs_destroy_inode, | 131 | .destroy_inode = nfs_destroy_inode, |
131 | .write_inode = nfs_write_inode, | 132 | .write_inode = nfs_write_inode, |
@@ -1044,7 +1045,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags, | |||
1044 | nfs4_fill_super(s); | 1045 | nfs4_fill_super(s); |
1045 | } | 1046 | } |
1046 | 1047 | ||
1047 | mntroot = nfs4_get_root(s, data->fh); | 1048 | mntroot = nfs4_get_root(s, &mntfh); |
1048 | if (IS_ERR(mntroot)) { | 1049 | if (IS_ERR(mntroot)) { |
1049 | error = PTR_ERR(mntroot); | 1050 | error = PTR_ERR(mntroot); |
1050 | goto error_splat_super; | 1051 | goto error_splat_super; |
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 525c136c7d8c..f4a0548b9ce8 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c | |||
@@ -78,7 +78,7 @@ read_failed: | |||
78 | /* | 78 | /* |
79 | * symlinks can't do much... | 79 | * symlinks can't do much... |
80 | */ | 80 | */ |
81 | struct inode_operations nfs_symlink_inode_operations = { | 81 | const struct inode_operations nfs_symlink_inode_operations = { |
82 | .readlink = generic_readlink, | 82 | .readlink = generic_readlink, |
83 | .follow_link = nfs_follow_link, | 83 | .follow_link = nfs_follow_link, |
84 | .put_link = page_put_link, | 84 | .put_link = page_put_link, |
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c index 3ea50ac64820..fcdcafbb3293 100644 --- a/fs/nfs/sysctl.c +++ b/fs/nfs/sysctl.c | |||
@@ -75,7 +75,7 @@ static ctl_table nfs_cb_sysctl_root[] = { | |||
75 | 75 | ||
76 | int nfs_register_sysctl(void) | 76 | int nfs_register_sysctl(void) |
77 | { | 77 | { |
78 | nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root, 0); | 78 | nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root); |
79 | if (nfs_callback_sysctl_table == NULL) | 79 | if (nfs_callback_sysctl_table == NULL) |
80 | return -ENOMEM; | 80 | return -ENOMEM; |
81 | return 0; | 81 | return 0; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 345492e78643..febdade91670 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1,47 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/fs/nfs/write.c | 2 | * linux/fs/nfs/write.c |
3 | * | 3 | * |
4 | * Writing file data over NFS. | 4 | * Write file data over NFS. |
5 | * | ||
6 | * We do it like this: When a (user) process wishes to write data to an | ||
7 | * NFS file, a write request is allocated that contains the RPC task data | ||
8 | * plus some info on the page to be written, and added to the inode's | ||
9 | * write chain. If the process writes past the end of the page, an async | ||
10 | * RPC call to write the page is scheduled immediately; otherwise, the call | ||
11 | * is delayed for a few seconds. | ||
12 | * | ||
13 | * Just like readahead, no async I/O is performed if wsize < PAGE_SIZE. | ||
14 | * | ||
15 | * Write requests are kept on the inode's writeback list. Each entry in | ||
16 | * that list references the page (portion) to be written. When the | ||
17 | * cache timeout has expired, the RPC task is woken up, and tries to | ||
18 | * lock the page. As soon as it manages to do so, the request is moved | ||
19 | * from the writeback list to the writelock list. | ||
20 | * | ||
21 | * Note: we must make sure never to confuse the inode passed in the | ||
22 | * write_page request with the one in page->inode. As far as I understand | ||
23 | * it, these are different when doing a swap-out. | ||
24 | * | ||
25 | * To understand everything that goes on here and in the NFS read code, | ||
26 | * one should be aware that a page is locked in exactly one of the following | ||
27 | * cases: | ||
28 | * | ||
29 | * - A write request is in progress. | ||
30 | * - A user process is in generic_file_write/nfs_update_page | ||
31 | * - A user process is in generic_file_read | ||
32 | * | ||
33 | * Also note that because of the way pages are invalidated in | ||
34 | * nfs_revalidate_inode, the following assertions hold: | ||
35 | * | ||
36 | * - If a page is dirty, there will be no read requests (a page will | ||
37 | * not be re-read unless invalidated by nfs_revalidate_inode). | ||
38 | * - If the page is not uptodate, there will be no pending write | ||
39 | * requests, and no process will be in nfs_update_page. | ||
40 | * | ||
41 | * FIXME: Interaction with the vmscan routines is not optimal yet. | ||
42 | * Either vmscan must be made nfs-savvy, or we need a different page | ||
43 | * reclaim concept that supports something like FS-independent | ||
44 | * buffer_heads with a b_ops-> field. | ||
45 | * | 5 | * |
46 | * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de> | 6 | * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de> |
47 | */ | 7 | */ |
@@ -79,7 +39,6 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context*, | |||
79 | unsigned int, unsigned int); | 39 | unsigned int, unsigned int); |
80 | static void nfs_mark_request_dirty(struct nfs_page *req); | 40 | static void nfs_mark_request_dirty(struct nfs_page *req); |
81 | static int nfs_wait_on_write_congestion(struct address_space *, int); | 41 | static int nfs_wait_on_write_congestion(struct address_space *, int); |
82 | static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int); | ||
83 | static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how); | 42 | static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how); |
84 | static const struct rpc_call_ops nfs_write_partial_ops; | 43 | static const struct rpc_call_ops nfs_write_partial_ops; |
85 | static const struct rpc_call_ops nfs_write_full_ops; | 44 | static const struct rpc_call_ops nfs_write_full_ops; |
@@ -194,6 +153,13 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c | |||
194 | i_size_write(inode, end); | 153 | i_size_write(inode, end); |
195 | } | 154 | } |
196 | 155 | ||
156 | /* A writeback failed: mark the page as bad, and invalidate the page cache */ | ||
157 | static void nfs_set_pageerror(struct page *page) | ||
158 | { | ||
159 | SetPageError(page); | ||
160 | nfs_zap_mapping(page->mapping->host, page->mapping); | ||
161 | } | ||
162 | |||
197 | /* We can set the PG_uptodate flag if we see that a write request | 163 | /* We can set the PG_uptodate flag if we see that a write request |
198 | * covers the full page. | 164 | * covers the full page. |
199 | */ | 165 | */ |
@@ -323,7 +289,7 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc | |||
323 | err = 0; | 289 | err = 0; |
324 | out: | 290 | out: |
325 | if (!wbc->for_writepages) | 291 | if (!wbc->for_writepages) |
326 | nfs_flush_mapping(page->mapping, wbc, wb_priority(wbc)); | 292 | nfs_flush_mapping(page->mapping, wbc, FLUSH_STABLE|wb_priority(wbc)); |
327 | return err; | 293 | return err; |
328 | } | 294 | } |
329 | 295 | ||
@@ -360,14 +326,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
360 | if (err < 0) | 326 | if (err < 0) |
361 | goto out; | 327 | goto out; |
362 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, err); | 328 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, err); |
363 | if (!wbc->nonblocking && wbc->sync_mode == WB_SYNC_ALL) { | 329 | err = 0; |
364 | err = nfs_wait_on_requests(inode, 0, 0); | ||
365 | if (err < 0) | ||
366 | goto out; | ||
367 | } | ||
368 | err = nfs_commit_inode(inode, wb_priority(wbc)); | ||
369 | if (err > 0) | ||
370 | err = 0; | ||
371 | out: | 330 | out: |
372 | clear_bit(BDI_write_congested, &bdi->state); | 331 | clear_bit(BDI_write_congested, &bdi->state); |
373 | wake_up_all(&nfs_write_congestion); | 332 | wake_up_all(&nfs_write_congestion); |
@@ -516,17 +475,6 @@ static int nfs_wait_on_requests_locked(struct inode *inode, unsigned long idx_st | |||
516 | return res; | 475 | return res; |
517 | } | 476 | } |
518 | 477 | ||
519 | static int nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int npages) | ||
520 | { | ||
521 | struct nfs_inode *nfsi = NFS_I(inode); | ||
522 | int ret; | ||
523 | |||
524 | spin_lock(&nfsi->req_lock); | ||
525 | ret = nfs_wait_on_requests_locked(inode, idx_start, npages); | ||
526 | spin_unlock(&nfsi->req_lock); | ||
527 | return ret; | ||
528 | } | ||
529 | |||
530 | static void nfs_cancel_dirty_list(struct list_head *head) | 478 | static void nfs_cancel_dirty_list(struct list_head *head) |
531 | { | 479 | { |
532 | struct nfs_page *req; | 480 | struct nfs_page *req; |
@@ -773,7 +721,7 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
773 | dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n", | 721 | dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n", |
774 | status, (long long)i_size_read(inode)); | 722 | status, (long long)i_size_read(inode)); |
775 | if (status < 0) | 723 | if (status < 0) |
776 | ClearPageUptodate(page); | 724 | nfs_set_pageerror(page); |
777 | return status; | 725 | return status; |
778 | } | 726 | } |
779 | 727 | ||
@@ -852,7 +800,8 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
852 | data->task.tk_priority = flush_task_priority(how); | 800 | data->task.tk_priority = flush_task_priority(how); |
853 | data->task.tk_cookie = (unsigned long)inode; | 801 | data->task.tk_cookie = (unsigned long)inode; |
854 | 802 | ||
855 | dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n", | 803 | dprintk("NFS: %5u initiated write call " |
804 | "(req %s/%Ld, %u bytes @ offset %Lu)\n", | ||
856 | data->task.tk_pid, | 805 | data->task.tk_pid, |
857 | inode->i_sb->s_id, | 806 | inode->i_sb->s_id, |
858 | (long long)NFS_FILEID(inode), | 807 | (long long)NFS_FILEID(inode), |
@@ -1034,8 +983,7 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | |||
1034 | return; | 983 | return; |
1035 | 984 | ||
1036 | if (task->tk_status < 0) { | 985 | if (task->tk_status < 0) { |
1037 | ClearPageUptodate(page); | 986 | nfs_set_pageerror(page); |
1038 | SetPageError(page); | ||
1039 | req->wb_context->error = task->tk_status; | 987 | req->wb_context->error = task->tk_status; |
1040 | dprintk(", error = %d\n", task->tk_status); | 988 | dprintk(", error = %d\n", task->tk_status); |
1041 | } else { | 989 | } else { |
@@ -1092,8 +1040,7 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) | |||
1092 | (long long)req_offset(req)); | 1040 | (long long)req_offset(req)); |
1093 | 1041 | ||
1094 | if (task->tk_status < 0) { | 1042 | if (task->tk_status < 0) { |
1095 | ClearPageUptodate(page); | 1043 | nfs_set_pageerror(page); |
1096 | SetPageError(page); | ||
1097 | req->wb_context->error = task->tk_status; | 1044 | req->wb_context->error = task->tk_status; |
1098 | end_page_writeback(page); | 1045 | end_page_writeback(page); |
1099 | nfs_inode_remove_request(req); | 1046 | nfs_inode_remove_request(req); |
@@ -1134,7 +1081,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1134 | struct nfs_writeres *resp = &data->res; | 1081 | struct nfs_writeres *resp = &data->res; |
1135 | int status; | 1082 | int status; |
1136 | 1083 | ||
1137 | dprintk("NFS: %4d nfs_writeback_done (status %d)\n", | 1084 | dprintk("NFS: %5u nfs_writeback_done (status %d)\n", |
1138 | task->tk_pid, task->tk_status); | 1085 | task->tk_pid, task->tk_status); |
1139 | 1086 | ||
1140 | /* | 1087 | /* |
@@ -1250,7 +1197,7 @@ static void nfs_commit_rpcsetup(struct list_head *head, | |||
1250 | data->task.tk_priority = flush_task_priority(how); | 1197 | data->task.tk_priority = flush_task_priority(how); |
1251 | data->task.tk_cookie = (unsigned long)inode; | 1198 | data->task.tk_cookie = (unsigned long)inode; |
1252 | 1199 | ||
1253 | dprintk("NFS: %4d initiated commit call\n", data->task.tk_pid); | 1200 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); |
1254 | } | 1201 | } |
1255 | 1202 | ||
1256 | /* | 1203 | /* |
@@ -1291,7 +1238,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
1291 | struct nfs_write_data *data = calldata; | 1238 | struct nfs_write_data *data = calldata; |
1292 | struct nfs_page *req; | 1239 | struct nfs_page *req; |
1293 | 1240 | ||
1294 | dprintk("NFS: %4d nfs_commit_done (status %d)\n", | 1241 | dprintk("NFS: %5u nfs_commit_done (status %d)\n", |
1295 | task->tk_pid, task->tk_status); | 1242 | task->tk_pid, task->tk_status); |
1296 | 1243 | ||
1297 | /* Call the NFS version-specific code */ | 1244 | /* Call the NFS version-specific code */ |
@@ -1516,6 +1463,8 @@ int nfs_wb_page_priority(struct inode *inode, struct page *page, int how) | |||
1516 | if (ret < 0) | 1463 | if (ret < 0) |
1517 | goto out; | 1464 | goto out; |
1518 | } | 1465 | } |
1466 | if (!PagePrivate(page)) | ||
1467 | return 0; | ||
1519 | ret = nfs_sync_mapping_wait(page->mapping, &wbc, how); | 1468 | ret = nfs_sync_mapping_wait(page->mapping, &wbc, how); |
1520 | if (ret >= 0) | 1469 | if (ret >= 0) |
1521 | return 0; | 1470 | return 0; |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 49c310b84923..6f24768272a1 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -16,7 +16,6 @@ | |||
16 | 16 | ||
17 | #include <linux/unistd.h> | 17 | #include <linux/unistd.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/sched.h> | ||
20 | #include <linux/stat.h> | 19 | #include <linux/stat.h> |
21 | #include <linux/in.h> | 20 | #include <linux/in.h> |
22 | #include <linux/seq_file.h> | 21 | #include <linux/seq_file.h> |
@@ -190,18 +189,17 @@ static int expkey_show(struct seq_file *m, | |||
190 | struct cache_head *h) | 189 | struct cache_head *h) |
191 | { | 190 | { |
192 | struct svc_expkey *ek ; | 191 | struct svc_expkey *ek ; |
192 | int i; | ||
193 | 193 | ||
194 | if (h ==NULL) { | 194 | if (h ==NULL) { |
195 | seq_puts(m, "#domain fsidtype fsid [path]\n"); | 195 | seq_puts(m, "#domain fsidtype fsid [path]\n"); |
196 | return 0; | 196 | return 0; |
197 | } | 197 | } |
198 | ek = container_of(h, struct svc_expkey, h); | 198 | ek = container_of(h, struct svc_expkey, h); |
199 | seq_printf(m, "%s %d 0x%08x", ek->ek_client->name, | 199 | seq_printf(m, "%s %d 0x", ek->ek_client->name, |
200 | ek->ek_fsidtype, ek->ek_fsid[0]); | 200 | ek->ek_fsidtype); |
201 | if (ek->ek_fsidtype != 1) | 201 | for (i=0; i < key_len(ek->ek_fsidtype)/4; i++) |
202 | seq_printf(m, "%08x", ek->ek_fsid[1]); | 202 | seq_printf(m, "%08x", ek->ek_fsid[i]); |
203 | if (ek->ek_fsidtype == 2) | ||
204 | seq_printf(m, "%08x", ek->ek_fsid[2]); | ||
205 | if (test_bit(CACHE_VALID, &h->flags) && | 203 | if (test_bit(CACHE_VALID, &h->flags) && |
206 | !test_bit(CACHE_NEGATIVE, &h->flags)) { | 204 | !test_bit(CACHE_NEGATIVE, &h->flags)) { |
207 | seq_printf(m, " "); | 205 | seq_printf(m, " "); |
@@ -232,9 +230,8 @@ static inline void expkey_init(struct cache_head *cnew, | |||
232 | kref_get(&item->ek_client->ref); | 230 | kref_get(&item->ek_client->ref); |
233 | new->ek_client = item->ek_client; | 231 | new->ek_client = item->ek_client; |
234 | new->ek_fsidtype = item->ek_fsidtype; | 232 | new->ek_fsidtype = item->ek_fsidtype; |
235 | new->ek_fsid[0] = item->ek_fsid[0]; | 233 | |
236 | new->ek_fsid[1] = item->ek_fsid[1]; | 234 | memcpy(new->ek_fsid, item->ek_fsid, sizeof(new->ek_fsid)); |
237 | new->ek_fsid[2] = item->ek_fsid[2]; | ||
238 | } | 235 | } |
239 | 236 | ||
240 | static inline void expkey_update(struct cache_head *cnew, | 237 | static inline void expkey_update(struct cache_head *cnew, |
@@ -363,7 +360,7 @@ static struct svc_export *svc_export_update(struct svc_export *new, | |||
363 | struct svc_export *old); | 360 | struct svc_export *old); |
364 | static struct svc_export *svc_export_lookup(struct svc_export *); | 361 | static struct svc_export *svc_export_lookup(struct svc_export *); |
365 | 362 | ||
366 | static int check_export(struct inode *inode, int flags) | 363 | static int check_export(struct inode *inode, int flags, unsigned char *uuid) |
367 | { | 364 | { |
368 | 365 | ||
369 | /* We currently export only dirs and regular files. | 366 | /* We currently export only dirs and regular files. |
@@ -376,12 +373,13 @@ static int check_export(struct inode *inode, int flags) | |||
376 | /* There are two requirements on a filesystem to be exportable. | 373 | /* There are two requirements on a filesystem to be exportable. |
377 | * 1: We must be able to identify the filesystem from a number. | 374 | * 1: We must be able to identify the filesystem from a number. |
378 | * either a device number (so FS_REQUIRES_DEV needed) | 375 | * either a device number (so FS_REQUIRES_DEV needed) |
379 | * or an FSID number (so NFSEXP_FSID needed). | 376 | * or an FSID number (so NFSEXP_FSID or ->uuid is needed). |
380 | * 2: We must be able to find an inode from a filehandle. | 377 | * 2: We must be able to find an inode from a filehandle. |
381 | * This means that s_export_op must be set. | 378 | * This means that s_export_op must be set. |
382 | */ | 379 | */ |
383 | if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) && | 380 | if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) && |
384 | !(flags & NFSEXP_FSID)) { | 381 | !(flags & NFSEXP_FSID) && |
382 | uuid == NULL) { | ||
385 | dprintk("exp_export: export of non-dev fs without fsid\n"); | 383 | dprintk("exp_export: export of non-dev fs without fsid\n"); |
386 | return -EINVAL; | 384 | return -EINVAL; |
387 | } | 385 | } |
@@ -406,10 +404,6 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) | |||
406 | int len; | 404 | int len; |
407 | int migrated, i, err; | 405 | int migrated, i, err; |
408 | 406 | ||
409 | len = qword_get(mesg, buf, PAGE_SIZE); | ||
410 | if (len != 5 || memcmp(buf, "fsloc", 5)) | ||
411 | return 0; | ||
412 | |||
413 | /* listsize */ | 407 | /* listsize */ |
414 | err = get_int(mesg, &fsloc->locations_count); | 408 | err = get_int(mesg, &fsloc->locations_count); |
415 | if (err) | 409 | if (err) |
@@ -520,6 +514,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
520 | exp.ex_fslocs.locations_count = 0; | 514 | exp.ex_fslocs.locations_count = 0; |
521 | exp.ex_fslocs.migrated = 0; | 515 | exp.ex_fslocs.migrated = 0; |
522 | 516 | ||
517 | exp.ex_uuid = NULL; | ||
518 | |||
523 | /* flags */ | 519 | /* flags */ |
524 | err = get_int(&mesg, &an_int); | 520 | err = get_int(&mesg, &an_int); |
525 | if (err == -ENOENT) | 521 | if (err == -ENOENT) |
@@ -543,12 +539,33 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
543 | if (err) goto out; | 539 | if (err) goto out; |
544 | exp.ex_fsid = an_int; | 540 | exp.ex_fsid = an_int; |
545 | 541 | ||
546 | err = check_export(nd.dentry->d_inode, exp.ex_flags); | 542 | while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) { |
547 | if (err) goto out; | 543 | if (strcmp(buf, "fsloc") == 0) |
544 | err = fsloc_parse(&mesg, buf, &exp.ex_fslocs); | ||
545 | else if (strcmp(buf, "uuid") == 0) { | ||
546 | /* expect a 16 byte uuid encoded as \xXXXX... */ | ||
547 | len = qword_get(&mesg, buf, PAGE_SIZE); | ||
548 | if (len != 16) | ||
549 | err = -EINVAL; | ||
550 | else { | ||
551 | exp.ex_uuid = | ||
552 | kmemdup(buf, 16, GFP_KERNEL); | ||
553 | if (exp.ex_uuid == NULL) | ||
554 | err = -ENOMEM; | ||
555 | } | ||
556 | } else | ||
557 | /* quietly ignore unknown words and anything | ||
558 | * following. Newer user-space can try to set | ||
559 | * new values, then see what the result was. | ||
560 | */ | ||
561 | break; | ||
562 | if (err) | ||
563 | goto out; | ||
564 | } | ||
548 | 565 | ||
549 | err = fsloc_parse(&mesg, buf, &exp.ex_fslocs); | 566 | err = check_export(nd.dentry->d_inode, exp.ex_flags, |
550 | if (err) | 567 | exp.ex_uuid); |
551 | goto out; | 568 | if (err) goto out; |
552 | } | 569 | } |
553 | 570 | ||
554 | expp = svc_export_lookup(&exp); | 571 | expp = svc_export_lookup(&exp); |
@@ -562,6 +579,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
562 | else | 579 | else |
563 | exp_put(expp); | 580 | exp_put(expp); |
564 | out: | 581 | out: |
582 | nfsd4_fslocs_free(&exp.ex_fslocs); | ||
583 | kfree(exp.ex_uuid); | ||
565 | kfree(exp.ex_path); | 584 | kfree(exp.ex_path); |
566 | if (nd.dentry) | 585 | if (nd.dentry) |
567 | path_release(&nd); | 586 | path_release(&nd); |
@@ -591,9 +610,19 @@ static int svc_export_show(struct seq_file *m, | |||
591 | seq_escape(m, exp->ex_client->name, " \t\n\\"); | 610 | seq_escape(m, exp->ex_client->name, " \t\n\\"); |
592 | seq_putc(m, '('); | 611 | seq_putc(m, '('); |
593 | if (test_bit(CACHE_VALID, &h->flags) && | 612 | if (test_bit(CACHE_VALID, &h->flags) && |
594 | !test_bit(CACHE_NEGATIVE, &h->flags)) | 613 | !test_bit(CACHE_NEGATIVE, &h->flags)) { |
595 | exp_flags(m, exp->ex_flags, exp->ex_fsid, | 614 | exp_flags(m, exp->ex_flags, exp->ex_fsid, |
596 | exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs); | 615 | exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs); |
616 | if (exp->ex_uuid) { | ||
617 | int i; | ||
618 | seq_puts(m, ",uuid="); | ||
619 | for (i=0; i<16; i++) { | ||
620 | if ((i&3) == 0 && i) | ||
621 | seq_putc(m, ':'); | ||
622 | seq_printf(m, "%02x", exp->ex_uuid[i]); | ||
623 | } | ||
624 | } | ||
625 | } | ||
597 | seq_puts(m, ")\n"); | 626 | seq_puts(m, ")\n"); |
598 | return 0; | 627 | return 0; |
599 | } | 628 | } |
@@ -630,6 +659,8 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem) | |||
630 | new->ex_anon_uid = item->ex_anon_uid; | 659 | new->ex_anon_uid = item->ex_anon_uid; |
631 | new->ex_anon_gid = item->ex_anon_gid; | 660 | new->ex_anon_gid = item->ex_anon_gid; |
632 | new->ex_fsid = item->ex_fsid; | 661 | new->ex_fsid = item->ex_fsid; |
662 | new->ex_uuid = item->ex_uuid; | ||
663 | item->ex_uuid = NULL; | ||
633 | new->ex_path = item->ex_path; | 664 | new->ex_path = item->ex_path; |
634 | item->ex_path = NULL; | 665 | item->ex_path = NULL; |
635 | new->ex_fslocs.locations = item->ex_fslocs.locations; | 666 | new->ex_fslocs.locations = item->ex_fslocs.locations; |
@@ -752,11 +783,11 @@ exp_get_key(svc_client *clp, dev_t dev, ino_t ino) | |||
752 | u32 fsidv[3]; | 783 | u32 fsidv[3]; |
753 | 784 | ||
754 | if (old_valid_dev(dev)) { | 785 | if (old_valid_dev(dev)) { |
755 | mk_fsid_v0(fsidv, dev, ino); | 786 | mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL); |
756 | return exp_find_key(clp, 0, fsidv, NULL); | 787 | return exp_find_key(clp, FSID_DEV, fsidv, NULL); |
757 | } | 788 | } |
758 | mk_fsid_v3(fsidv, dev, ino); | 789 | mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL); |
759 | return exp_find_key(clp, 3, fsidv, NULL); | 790 | return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL); |
760 | } | 791 | } |
761 | 792 | ||
762 | /* | 793 | /* |
@@ -767,9 +798,9 @@ exp_get_fsid_key(svc_client *clp, int fsid) | |||
767 | { | 798 | { |
768 | u32 fsidv[2]; | 799 | u32 fsidv[2]; |
769 | 800 | ||
770 | mk_fsid_v1(fsidv, fsid); | 801 | mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL); |
771 | 802 | ||
772 | return exp_find_key(clp, 1, fsidv, NULL); | 803 | return exp_find_key(clp, FSID_NUM, fsidv, NULL); |
773 | } | 804 | } |
774 | 805 | ||
775 | svc_export * | 806 | svc_export * |
@@ -883,8 +914,8 @@ static int exp_fsid_hash(svc_client *clp, struct svc_export *exp) | |||
883 | if ((exp->ex_flags & NFSEXP_FSID) == 0) | 914 | if ((exp->ex_flags & NFSEXP_FSID) == 0) |
884 | return 0; | 915 | return 0; |
885 | 916 | ||
886 | mk_fsid_v1(fsid, exp->ex_fsid); | 917 | mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL); |
887 | return exp_set_key(clp, 1, fsid, exp); | 918 | return exp_set_key(clp, FSID_NUM, fsid, exp); |
888 | } | 919 | } |
889 | 920 | ||
890 | static int exp_hash(struct auth_domain *clp, struct svc_export *exp) | 921 | static int exp_hash(struct auth_domain *clp, struct svc_export *exp) |
@@ -894,11 +925,11 @@ static int exp_hash(struct auth_domain *clp, struct svc_export *exp) | |||
894 | dev_t dev = inode->i_sb->s_dev; | 925 | dev_t dev = inode->i_sb->s_dev; |
895 | 926 | ||
896 | if (old_valid_dev(dev)) { | 927 | if (old_valid_dev(dev)) { |
897 | mk_fsid_v0(fsid, dev, inode->i_ino); | 928 | mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL); |
898 | return exp_set_key(clp, 0, fsid, exp); | 929 | return exp_set_key(clp, FSID_DEV, fsid, exp); |
899 | } | 930 | } |
900 | mk_fsid_v3(fsid, dev, inode->i_ino); | 931 | mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL); |
901 | return exp_set_key(clp, 3, fsid, exp); | 932 | return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp); |
902 | } | 933 | } |
903 | 934 | ||
904 | static void exp_unhash(struct svc_export *exp) | 935 | static void exp_unhash(struct svc_export *exp) |
@@ -977,7 +1008,7 @@ exp_export(struct nfsctl_export *nxp) | |||
977 | goto finish; | 1008 | goto finish; |
978 | } | 1009 | } |
979 | 1010 | ||
980 | err = check_export(nd.dentry->d_inode, nxp->ex_flags); | 1011 | err = check_export(nd.dentry->d_inode, nxp->ex_flags, NULL); |
981 | if (err) goto finish; | 1012 | if (err) goto finish; |
982 | 1013 | ||
983 | err = -ENOMEM; | 1014 | err = -ENOMEM; |
@@ -1170,9 +1201,9 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
1170 | __be32 rv; | 1201 | __be32 rv; |
1171 | u32 fsidv[2]; | 1202 | u32 fsidv[2]; |
1172 | 1203 | ||
1173 | mk_fsid_v1(fsidv, 0); | 1204 | mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); |
1174 | 1205 | ||
1175 | exp = exp_find(clp, 1, fsidv, creq); | 1206 | exp = exp_find(clp, FSID_NUM, fsidv, creq); |
1176 | if (IS_ERR(exp)) | 1207 | if (IS_ERR(exp)) |
1177 | return nfserrno(PTR_ERR(exp)); | 1208 | return nfserrno(PTR_ERR(exp)); |
1178 | if (exp == NULL) | 1209 | if (exp == NULL) |
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index edde5dc5f796..b61742885011 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c | |||
@@ -287,13 +287,20 @@ static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, __be32 *p, | |||
287 | return 1; | 287 | return 1; |
288 | } | 288 | } |
289 | 289 | ||
290 | static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, __be32 *p, | 290 | static int nfsaclsvc_release_attrstat(struct svc_rqst *rqstp, __be32 *p, |
291 | struct nfsd_fhandle *resp) | 291 | struct nfsd_attrstat *resp) |
292 | { | 292 | { |
293 | fh_put(&resp->fh); | 293 | fh_put(&resp->fh); |
294 | return 1; | 294 | return 1; |
295 | } | 295 | } |
296 | 296 | ||
297 | static int nfsaclsvc_release_access(struct svc_rqst *rqstp, __be32 *p, | ||
298 | struct nfsd3_accessres *resp) | ||
299 | { | ||
300 | fh_put(&resp->fh); | ||
301 | return 1; | ||
302 | } | ||
303 | |||
297 | #define nfsaclsvc_decode_voidargs NULL | 304 | #define nfsaclsvc_decode_voidargs NULL |
298 | #define nfsaclsvc_encode_voidres NULL | 305 | #define nfsaclsvc_encode_voidres NULL |
299 | #define nfsaclsvc_release_void NULL | 306 | #define nfsaclsvc_release_void NULL |
@@ -322,9 +329,9 @@ struct nfsd3_voidargs { int dummy; }; | |||
322 | static struct svc_procedure nfsd_acl_procedures2[] = { | 329 | static struct svc_procedure nfsd_acl_procedures2[] = { |
323 | PROC(null, void, void, void, RC_NOCACHE, ST), | 330 | PROC(null, void, void, void, RC_NOCACHE, ST), |
324 | PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)), | 331 | PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)), |
325 | PROC(setacl, setacl, attrstat, fhandle, RC_NOCACHE, ST+AT), | 332 | PROC(setacl, setacl, attrstat, attrstat, RC_NOCACHE, ST+AT), |
326 | PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT), | 333 | PROC(getattr, fhandle, attrstat, attrstat, RC_NOCACHE, ST+AT), |
327 | PROC(access, access, access, fhandle, RC_NOCACHE, ST+AT+1), | 334 | PROC(access, access, access, access, RC_NOCACHE, ST+AT+1), |
328 | }; | 335 | }; |
329 | 336 | ||
330 | struct svc_version nfsd_acl_version2 = { | 337 | struct svc_version nfsd_acl_version2 = { |
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index e695660921ec..6f677988c71d 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
@@ -149,6 +149,27 @@ decode_sattr3(__be32 *p, struct iattr *iap) | |||
149 | return p; | 149 | return p; |
150 | } | 150 | } |
151 | 151 | ||
152 | static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp) | ||
153 | { | ||
154 | u64 f; | ||
155 | switch(fsid_source(fhp)) { | ||
156 | default: | ||
157 | case FSIDSOURCE_DEV: | ||
158 | p = xdr_encode_hyper(p, (u64)huge_encode_dev | ||
159 | (fhp->fh_dentry->d_inode->i_sb->s_dev)); | ||
160 | break; | ||
161 | case FSIDSOURCE_FSID: | ||
162 | p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid); | ||
163 | break; | ||
164 | case FSIDSOURCE_UUID: | ||
165 | f = ((u64*)fhp->fh_export->ex_uuid)[0]; | ||
166 | f ^= ((u64*)fhp->fh_export->ex_uuid)[1]; | ||
167 | p = xdr_encode_hyper(p, f); | ||
168 | break; | ||
169 | } | ||
170 | return p; | ||
171 | } | ||
172 | |||
152 | static __be32 * | 173 | static __be32 * |
153 | encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | 174 | encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, |
154 | struct kstat *stat) | 175 | struct kstat *stat) |
@@ -169,10 +190,7 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
169 | p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9); | 190 | p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9); |
170 | *p++ = htonl((u32) MAJOR(stat->rdev)); | 191 | *p++ = htonl((u32) MAJOR(stat->rdev)); |
171 | *p++ = htonl((u32) MINOR(stat->rdev)); | 192 | *p++ = htonl((u32) MINOR(stat->rdev)); |
172 | if (is_fsid(fhp, rqstp->rq_reffh)) | 193 | p = encode_fsid(p, fhp); |
173 | p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid); | ||
174 | else | ||
175 | p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat->dev)); | ||
176 | p = xdr_encode_hyper(p, (u64) stat->ino); | 194 | p = xdr_encode_hyper(p, (u64) stat->ino); |
177 | p = encode_time3(p, &stat->atime); | 195 | p = encode_time3(p, &stat->atime); |
178 | lease_get_mtime(dentry->d_inode, &time); | 196 | lease_get_mtime(dentry->d_inode, &time); |
@@ -203,10 +221,7 @@ encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) | |||
203 | p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9); | 221 | p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9); |
204 | *p++ = fhp->fh_post_rdev[0]; | 222 | *p++ = fhp->fh_post_rdev[0]; |
205 | *p++ = fhp->fh_post_rdev[1]; | 223 | *p++ = fhp->fh_post_rdev[1]; |
206 | if (is_fsid(fhp, rqstp->rq_reffh)) | 224 | p = encode_fsid(p, fhp); |
207 | p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid); | ||
208 | else | ||
209 | p = xdr_encode_hyper(p, (u64)huge_encode_dev(inode->i_sb->s_dev)); | ||
210 | p = xdr_encode_hyper(p, (u64) inode->i_ino); | 225 | p = xdr_encode_hyper(p, (u64) inode->i_ino); |
211 | p = encode_time3(p, &fhp->fh_post_atime); | 226 | p = encode_time3(p, &fhp->fh_post_atime); |
212 | p = encode_time3(p, &fhp->fh_post_mtime); | 227 | p = encode_time3(p, &fhp->fh_post_mtime); |
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 5d94555cdc83..832673b14587 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -61,9 +61,11 @@ | |||
61 | 61 | ||
62 | /* flags used to simulate posix default ACLs */ | 62 | /* flags used to simulate posix default ACLs */ |
63 | #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \ | 63 | #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \ |
64 | | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE) | 64 | | NFS4_ACE_DIRECTORY_INHERIT_ACE) |
65 | 65 | ||
66 | #define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS | NFS4_ACE_IDENTIFIER_GROUP) | 66 | #define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \ |
67 | | NFS4_ACE_INHERIT_ONLY_ACE \ | ||
68 | | NFS4_ACE_IDENTIFIER_GROUP) | ||
67 | 69 | ||
68 | #define MASK_EQUAL(mask1, mask2) \ | 70 | #define MASK_EQUAL(mask1, mask2) \ |
69 | ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) ) | 71 | ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) ) |
@@ -87,12 +89,19 @@ mask_from_posix(unsigned short perm, unsigned int flags) | |||
87 | } | 89 | } |
88 | 90 | ||
89 | static u32 | 91 | static u32 |
90 | deny_mask(u32 allow_mask, unsigned int flags) | 92 | deny_mask_from_posix(unsigned short perm, u32 flags) |
91 | { | 93 | { |
92 | u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP; | 94 | u32 mask = 0; |
93 | if (!(flags & NFS4_ACL_DIR)) | 95 | |
94 | ret &= ~NFS4_ACE_DELETE_CHILD; | 96 | if (perm & ACL_READ) |
95 | return ret; | 97 | mask |= NFS4_READ_MODE; |
98 | if (perm & ACL_WRITE) | ||
99 | mask |= NFS4_WRITE_MODE; | ||
100 | if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR)) | ||
101 | mask |= NFS4_ACE_DELETE_CHILD; | ||
102 | if (perm & ACL_EXECUTE) | ||
103 | mask |= NFS4_EXECUTE_MODE; | ||
104 | return mask; | ||
96 | } | 105 | } |
97 | 106 | ||
98 | /* XXX: modify functions to return NFS errors; they're only ever | 107 | /* XXX: modify functions to return NFS errors; they're only ever |
@@ -126,108 +135,151 @@ struct ace_container { | |||
126 | }; | 135 | }; |
127 | 136 | ||
128 | static short ace2type(struct nfs4_ace *); | 137 | static short ace2type(struct nfs4_ace *); |
129 | static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); | 138 | static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, |
130 | static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int); | 139 | unsigned int); |
131 | int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); | 140 | void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); |
132 | static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *); | ||
133 | 141 | ||
134 | struct nfs4_acl * | 142 | struct nfs4_acl * |
135 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, | 143 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, |
136 | unsigned int flags) | 144 | unsigned int flags) |
137 | { | 145 | { |
138 | struct nfs4_acl *acl; | 146 | struct nfs4_acl *acl; |
139 | int error = -EINVAL; | 147 | int size = 0; |
140 | 148 | ||
141 | if ((pacl != NULL && | 149 | if (pacl) { |
142 | (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) || | 150 | if (posix_acl_valid(pacl) < 0) |
143 | (dpacl != NULL && | 151 | return ERR_PTR(-EINVAL); |
144 | (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0))) | 152 | size += 2*pacl->a_count; |
145 | goto out_err; | ||
146 | |||
147 | acl = nfs4_acl_new(); | ||
148 | if (acl == NULL) { | ||
149 | error = -ENOMEM; | ||
150 | goto out_err; | ||
151 | } | 153 | } |
152 | 154 | if (dpacl) { | |
153 | if (pacl != NULL) { | 155 | if (posix_acl_valid(dpacl) < 0) |
154 | error = _posix_to_nfsv4_one(pacl, acl, | 156 | return ERR_PTR(-EINVAL); |
155 | flags & ~NFS4_ACL_TYPE_DEFAULT); | 157 | size += 2*dpacl->a_count; |
156 | if (error < 0) | ||
157 | goto out_acl; | ||
158 | } | 158 | } |
159 | 159 | ||
160 | if (dpacl != NULL) { | 160 | /* Allocate for worst case: one (deny, allow) pair each: */ |
161 | error = _posix_to_nfsv4_one(dpacl, acl, | 161 | acl = nfs4_acl_new(size); |
162 | flags | NFS4_ACL_TYPE_DEFAULT); | 162 | if (acl == NULL) |
163 | if (error < 0) | 163 | return ERR_PTR(-ENOMEM); |
164 | goto out_acl; | ||
165 | } | ||
166 | 164 | ||
167 | return acl; | 165 | if (pacl) |
166 | _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT); | ||
168 | 167 | ||
169 | out_acl: | 168 | if (dpacl) |
170 | nfs4_acl_free(acl); | 169 | _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT); |
171 | out_err: | ||
172 | acl = ERR_PTR(error); | ||
173 | 170 | ||
174 | return acl; | 171 | return acl; |
175 | } | 172 | } |
176 | 173 | ||
177 | static int | 174 | struct posix_acl_summary { |
178 | nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype, | 175 | unsigned short owner; |
179 | uid_t owner, unsigned int flags) | 176 | unsigned short users; |
177 | unsigned short group; | ||
178 | unsigned short groups; | ||
179 | unsigned short other; | ||
180 | unsigned short mask; | ||
181 | }; | ||
182 | |||
183 | static void | ||
184 | summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas) | ||
180 | { | 185 | { |
181 | int error; | 186 | struct posix_acl_entry *pa, *pe; |
182 | 187 | pas->users = 0; | |
183 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, | 188 | pas->groups = 0; |
184 | eflag, mask, whotype, owner); | 189 | pas->mask = 07; |
185 | if (error < 0) | 190 | |
186 | return error; | 191 | pe = acl->a_entries + acl->a_count; |
187 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 192 | |
188 | eflag, deny_mask(mask, flags), whotype, owner); | 193 | FOREACH_ACL_ENTRY(pa, acl, pe) { |
189 | return error; | 194 | switch (pa->e_tag) { |
195 | case ACL_USER_OBJ: | ||
196 | pas->owner = pa->e_perm; | ||
197 | break; | ||
198 | case ACL_GROUP_OBJ: | ||
199 | pas->group = pa->e_perm; | ||
200 | break; | ||
201 | case ACL_USER: | ||
202 | pas->users |= pa->e_perm; | ||
203 | break; | ||
204 | case ACL_GROUP: | ||
205 | pas->groups |= pa->e_perm; | ||
206 | break; | ||
207 | case ACL_OTHER: | ||
208 | pas->other = pa->e_perm; | ||
209 | break; | ||
210 | case ACL_MASK: | ||
211 | pas->mask = pa->e_perm; | ||
212 | break; | ||
213 | } | ||
214 | } | ||
215 | /* We'll only care about effective permissions: */ | ||
216 | pas->users &= pas->mask; | ||
217 | pas->group &= pas->mask; | ||
218 | pas->groups &= pas->mask; | ||
190 | } | 219 | } |
191 | 220 | ||
192 | /* We assume the acl has been verified with posix_acl_valid. */ | 221 | /* We assume the acl has been verified with posix_acl_valid. */ |
193 | static int | 222 | static void |
194 | _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | 223 | _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, |
195 | unsigned int flags) | 224 | unsigned int flags) |
196 | { | 225 | { |
197 | struct posix_acl_entry *pa, *pe, *group_owner_entry; | 226 | struct posix_acl_entry *pa, *group_owner_entry; |
198 | int error = -EINVAL; | 227 | struct nfs4_ace *ace; |
199 | u32 mask, mask_mask; | 228 | struct posix_acl_summary pas; |
229 | unsigned short deny; | ||
200 | int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? | 230 | int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? |
201 | NFS4_INHERITANCE_FLAGS : 0); | 231 | NFS4_INHERITANCE_FLAGS : 0); |
202 | 232 | ||
203 | BUG_ON(pacl->a_count < 3); | 233 | BUG_ON(pacl->a_count < 3); |
204 | pe = pacl->a_entries + pacl->a_count; | 234 | summarize_posix_acl(pacl, &pas); |
205 | pa = pe - 2; /* if mask entry exists, it's second from the last. */ | ||
206 | if (pa->e_tag == ACL_MASK) | ||
207 | mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags); | ||
208 | else | ||
209 | mask_mask = 0; | ||
210 | 235 | ||
211 | pa = pacl->a_entries; | 236 | pa = pacl->a_entries; |
212 | BUG_ON(pa->e_tag != ACL_USER_OBJ); | 237 | ace = acl->aces + acl->naces; |
213 | mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER); | ||
214 | error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags); | ||
215 | if (error < 0) | ||
216 | goto out; | ||
217 | pa++; | ||
218 | 238 | ||
219 | while (pa->e_tag == ACL_USER) { | 239 | /* We could deny everything not granted by the owner: */ |
220 | mask = mask_from_posix(pa->e_perm, flags); | 240 | deny = ~pas.owner; |
221 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 241 | /* |
222 | eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id); | 242 | * but it is equivalent (and simpler) to deny only what is not |
223 | if (error < 0) | 243 | * granted by later entries: |
224 | goto out; | 244 | */ |
245 | deny &= pas.users | pas.group | pas.groups | pas.other; | ||
246 | if (deny) { | ||
247 | ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE; | ||
248 | ace->flag = eflag; | ||
249 | ace->access_mask = deny_mask_from_posix(deny, flags); | ||
250 | ace->whotype = NFS4_ACL_WHO_OWNER; | ||
251 | ace++; | ||
252 | acl->naces++; | ||
253 | } | ||
225 | 254 | ||
255 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; | ||
256 | ace->flag = eflag; | ||
257 | ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER); | ||
258 | ace->whotype = NFS4_ACL_WHO_OWNER; | ||
259 | ace++; | ||
260 | acl->naces++; | ||
261 | pa++; | ||
226 | 262 | ||
227 | error = nfs4_acl_add_pair(acl, eflag, mask, | 263 | while (pa->e_tag == ACL_USER) { |
228 | NFS4_ACL_WHO_NAMED, pa->e_id, flags); | 264 | deny = ~(pa->e_perm & pas.mask); |
229 | if (error < 0) | 265 | deny &= pas.groups | pas.group | pas.other; |
230 | goto out; | 266 | if (deny) { |
267 | ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE; | ||
268 | ace->flag = eflag; | ||
269 | ace->access_mask = deny_mask_from_posix(deny, flags); | ||
270 | ace->whotype = NFS4_ACL_WHO_NAMED; | ||
271 | ace->who = pa->e_id; | ||
272 | ace++; | ||
273 | acl->naces++; | ||
274 | } | ||
275 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; | ||
276 | ace->flag = eflag; | ||
277 | ace->access_mask = mask_from_posix(pa->e_perm & pas.mask, | ||
278 | flags); | ||
279 | ace->whotype = NFS4_ACL_WHO_NAMED; | ||
280 | ace->who = pa->e_id; | ||
281 | ace++; | ||
282 | acl->naces++; | ||
231 | pa++; | 283 | pa++; |
232 | } | 284 | } |
233 | 285 | ||
@@ -236,67 +288,65 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | |||
236 | 288 | ||
237 | /* allow ACEs */ | 289 | /* allow ACEs */ |
238 | 290 | ||
239 | if (pacl->a_count > 3) { | ||
240 | BUG_ON(pa->e_tag != ACL_GROUP_OBJ); | ||
241 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | ||
242 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, | ||
243 | NFS4_ACL_WHO_GROUP, 0); | ||
244 | if (error < 0) | ||
245 | goto out; | ||
246 | } | ||
247 | group_owner_entry = pa; | 291 | group_owner_entry = pa; |
248 | mask = mask_from_posix(pa->e_perm, flags); | 292 | |
249 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, | 293 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; |
250 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, | 294 | ace->flag = eflag; |
251 | NFS4_ACL_WHO_GROUP, 0); | 295 | ace->access_mask = mask_from_posix(pas.group, flags); |
252 | if (error < 0) | 296 | ace->whotype = NFS4_ACL_WHO_GROUP; |
253 | goto out; | 297 | ace++; |
298 | acl->naces++; | ||
254 | pa++; | 299 | pa++; |
255 | 300 | ||
256 | while (pa->e_tag == ACL_GROUP) { | 301 | while (pa->e_tag == ACL_GROUP) { |
257 | mask = mask_from_posix(pa->e_perm, flags); | 302 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; |
258 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 303 | ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP; |
259 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, | 304 | ace->access_mask = mask_from_posix(pa->e_perm & pas.mask, |
260 | NFS4_ACL_WHO_NAMED, pa->e_id); | 305 | flags); |
261 | if (error < 0) | 306 | ace->whotype = NFS4_ACL_WHO_NAMED; |
262 | goto out; | 307 | ace->who = pa->e_id; |
263 | 308 | ace++; | |
264 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, | 309 | acl->naces++; |
265 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, | ||
266 | NFS4_ACL_WHO_NAMED, pa->e_id); | ||
267 | if (error < 0) | ||
268 | goto out; | ||
269 | pa++; | 310 | pa++; |
270 | } | 311 | } |
271 | 312 | ||
272 | /* deny ACEs */ | 313 | /* deny ACEs */ |
273 | 314 | ||
274 | pa = group_owner_entry; | 315 | pa = group_owner_entry; |
275 | mask = mask_from_posix(pa->e_perm, flags); | 316 | |
276 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 317 | deny = ~pas.group & pas.other; |
277 | NFS4_ACE_IDENTIFIER_GROUP | eflag, | 318 | if (deny) { |
278 | deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0); | 319 | ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE; |
279 | if (error < 0) | 320 | ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP; |
280 | goto out; | 321 | ace->access_mask = deny_mask_from_posix(deny, flags); |
322 | ace->whotype = NFS4_ACL_WHO_GROUP; | ||
323 | ace++; | ||
324 | acl->naces++; | ||
325 | } | ||
281 | pa++; | 326 | pa++; |
327 | |||
282 | while (pa->e_tag == ACL_GROUP) { | 328 | while (pa->e_tag == ACL_GROUP) { |
283 | mask = mask_from_posix(pa->e_perm, flags); | 329 | deny = ~(pa->e_perm & pas.mask); |
284 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 330 | deny &= pas.other; |
285 | NFS4_ACE_IDENTIFIER_GROUP | eflag, | 331 | if (deny) { |
286 | deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id); | 332 | ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE; |
287 | if (error < 0) | 333 | ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP; |
288 | goto out; | 334 | ace->access_mask = mask_from_posix(deny, flags); |
335 | ace->whotype = NFS4_ACL_WHO_NAMED; | ||
336 | ace->who = pa->e_id; | ||
337 | ace++; | ||
338 | acl->naces++; | ||
339 | } | ||
289 | pa++; | 340 | pa++; |
290 | } | 341 | } |
291 | 342 | ||
292 | if (pa->e_tag == ACL_MASK) | 343 | if (pa->e_tag == ACL_MASK) |
293 | pa++; | 344 | pa++; |
294 | BUG_ON(pa->e_tag != ACL_OTHER); | 345 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; |
295 | mask = mask_from_posix(pa->e_perm, flags); | 346 | ace->flag = eflag; |
296 | error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags); | 347 | ace->access_mask = mask_from_posix(pa->e_perm, flags); |
297 | 348 | ace->whotype = NFS4_ACL_WHO_EVERYONE; | |
298 | out: | 349 | acl->naces++; |
299 | return error; | ||
300 | } | 350 | } |
301 | 351 | ||
302 | static void | 352 | static void |
@@ -342,46 +392,6 @@ sort_pacl(struct posix_acl *pacl) | |||
342 | return; | 392 | return; |
343 | } | 393 | } |
344 | 394 | ||
345 | int | ||
346 | nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl, | ||
347 | struct posix_acl **dpacl, unsigned int flags) | ||
348 | { | ||
349 | struct nfs4_acl *dacl; | ||
350 | int error = -ENOMEM; | ||
351 | |||
352 | *pacl = NULL; | ||
353 | *dpacl = NULL; | ||
354 | |||
355 | dacl = nfs4_acl_new(); | ||
356 | if (dacl == NULL) | ||
357 | goto out; | ||
358 | |||
359 | error = nfs4_acl_split(acl, dacl); | ||
360 | if (error) | ||
361 | goto out_acl; | ||
362 | |||
363 | *pacl = _nfsv4_to_posix_one(acl, flags); | ||
364 | if (IS_ERR(*pacl)) { | ||
365 | error = PTR_ERR(*pacl); | ||
366 | *pacl = NULL; | ||
367 | goto out_acl; | ||
368 | } | ||
369 | |||
370 | *dpacl = _nfsv4_to_posix_one(dacl, flags); | ||
371 | if (IS_ERR(*dpacl)) { | ||
372 | error = PTR_ERR(*dpacl); | ||
373 | *dpacl = NULL; | ||
374 | } | ||
375 | out_acl: | ||
376 | if (error) { | ||
377 | posix_acl_release(*pacl); | ||
378 | *pacl = NULL; | ||
379 | } | ||
380 | nfs4_acl_free(dacl); | ||
381 | out: | ||
382 | return error; | ||
383 | } | ||
384 | |||
385 | /* | 395 | /* |
386 | * While processing the NFSv4 ACE, this maintains bitmasks representing | 396 | * While processing the NFSv4 ACE, this maintains bitmasks representing |
387 | * which permission bits have been allowed and which denied to a given | 397 | * which permission bits have been allowed and which denied to a given |
@@ -406,6 +416,7 @@ struct posix_ace_state_array { | |||
406 | * calculated so far: */ | 416 | * calculated so far: */ |
407 | 417 | ||
408 | struct posix_acl_state { | 418 | struct posix_acl_state { |
419 | int empty; | ||
409 | struct posix_ace_state owner; | 420 | struct posix_ace_state owner; |
410 | struct posix_ace_state group; | 421 | struct posix_ace_state group; |
411 | struct posix_ace_state other; | 422 | struct posix_ace_state other; |
@@ -421,6 +432,7 @@ init_state(struct posix_acl_state *state, int cnt) | |||
421 | int alloc; | 432 | int alloc; |
422 | 433 | ||
423 | memset(state, 0, sizeof(struct posix_acl_state)); | 434 | memset(state, 0, sizeof(struct posix_acl_state)); |
435 | state->empty = 1; | ||
424 | /* | 436 | /* |
425 | * In the worst case, each individual acl could be for a distinct | 437 | * In the worst case, each individual acl could be for a distinct |
426 | * named user or group, but we don't no which, so we allocate | 438 | * named user or group, but we don't no which, so we allocate |
@@ -488,6 +500,20 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) | |||
488 | int nace; | 500 | int nace; |
489 | int i, error = 0; | 501 | int i, error = 0; |
490 | 502 | ||
503 | /* | ||
504 | * ACLs with no ACEs are treated differently in the inheritable | ||
505 | * and effective cases: when there are no inheritable ACEs, we | ||
506 | * set a zero-length default posix acl: | ||
507 | */ | ||
508 | if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) { | ||
509 | pacl = posix_acl_alloc(0, GFP_KERNEL); | ||
510 | return pacl ? pacl : ERR_PTR(-ENOMEM); | ||
511 | } | ||
512 | /* | ||
513 | * When there are no effective ACEs, the following will end | ||
514 | * up setting a 3-element effective posix ACL with all | ||
515 | * permissions zero. | ||
516 | */ | ||
491 | nace = 4 + state->users->n + state->groups->n; | 517 | nace = 4 + state->users->n + state->groups->n; |
492 | pacl = posix_acl_alloc(nace, GFP_KERNEL); | 518 | pacl = posix_acl_alloc(nace, GFP_KERNEL); |
493 | if (!pacl) | 519 | if (!pacl) |
@@ -603,6 +629,8 @@ static void process_one_v4_ace(struct posix_acl_state *state, | |||
603 | u32 mask = ace->access_mask; | 629 | u32 mask = ace->access_mask; |
604 | int i; | 630 | int i; |
605 | 631 | ||
632 | state->empty = 0; | ||
633 | |||
606 | switch (ace2type(ace)) { | 634 | switch (ace2type(ace)) { |
607 | case ACL_USER_OBJ: | 635 | case ACL_USER_OBJ: |
608 | if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) { | 636 | if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) { |
@@ -666,75 +694,62 @@ static void process_one_v4_ace(struct posix_acl_state *state, | |||
666 | } | 694 | } |
667 | } | 695 | } |
668 | 696 | ||
669 | static struct posix_acl * | 697 | int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl, |
670 | _nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags) | 698 | struct posix_acl **dpacl, unsigned int flags) |
671 | { | 699 | { |
672 | struct posix_acl_state state; | 700 | struct posix_acl_state effective_acl_state, default_acl_state; |
673 | struct posix_acl *pacl; | ||
674 | struct nfs4_ace *ace; | 701 | struct nfs4_ace *ace; |
675 | int ret; | 702 | int ret; |
676 | 703 | ||
677 | ret = init_state(&state, n4acl->naces); | 704 | ret = init_state(&effective_acl_state, acl->naces); |
678 | if (ret) | 705 | if (ret) |
679 | return ERR_PTR(ret); | 706 | return ret; |
680 | 707 | ret = init_state(&default_acl_state, acl->naces); | |
681 | list_for_each_entry(ace, &n4acl->ace_head, l_ace) | 708 | if (ret) |
682 | process_one_v4_ace(&state, ace); | 709 | goto out_estate; |
683 | 710 | ret = -EINVAL; | |
684 | pacl = posix_state_to_acl(&state, flags); | 711 | for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { |
685 | |||
686 | free_state(&state); | ||
687 | |||
688 | if (!IS_ERR(pacl)) | ||
689 | sort_pacl(pacl); | ||
690 | return pacl; | ||
691 | } | ||
692 | |||
693 | static int | ||
694 | nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl) | ||
695 | { | ||
696 | struct list_head *h, *n; | ||
697 | struct nfs4_ace *ace; | ||
698 | int error = 0; | ||
699 | |||
700 | list_for_each_safe(h, n, &acl->ace_head) { | ||
701 | ace = list_entry(h, struct nfs4_ace, l_ace); | ||
702 | |||
703 | if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && | 712 | if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && |
704 | ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) | 713 | ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) |
705 | return -EINVAL; | 714 | goto out_dstate; |
706 | |||
707 | if (ace->flag & ~NFS4_SUPPORTED_FLAGS) | 715 | if (ace->flag & ~NFS4_SUPPORTED_FLAGS) |
708 | return -EINVAL; | 716 | goto out_dstate; |
709 | 717 | if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) { | |
710 | switch (ace->flag & NFS4_INHERITANCE_FLAGS) { | 718 | process_one_v4_ace(&effective_acl_state, ace); |
711 | case 0: | ||
712 | /* Leave this ace in the effective acl: */ | ||
713 | continue; | 719 | continue; |
714 | case NFS4_INHERITANCE_FLAGS: | ||
715 | /* Add this ace to the default acl and remove it | ||
716 | * from the effective acl: */ | ||
717 | error = nfs4_acl_add_ace(dacl, ace->type, ace->flag, | ||
718 | ace->access_mask, ace->whotype, ace->who); | ||
719 | if (error) | ||
720 | return error; | ||
721 | list_del(h); | ||
722 | kfree(ace); | ||
723 | acl->naces--; | ||
724 | break; | ||
725 | case NFS4_INHERITANCE_FLAGS & ~NFS4_ACE_INHERIT_ONLY_ACE: | ||
726 | /* Add this ace to the default, but leave it in | ||
727 | * the effective acl as well: */ | ||
728 | error = nfs4_acl_add_ace(dacl, ace->type, ace->flag, | ||
729 | ace->access_mask, ace->whotype, ace->who); | ||
730 | if (error) | ||
731 | return error; | ||
732 | break; | ||
733 | default: | ||
734 | return -EINVAL; | ||
735 | } | 720 | } |
721 | if (!(flags & NFS4_ACL_DIR)) | ||
722 | goto out_dstate; | ||
723 | /* | ||
724 | * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT | ||
725 | * is set, we're effectively turning on the other. That's OK, | ||
726 | * according to rfc 3530. | ||
727 | */ | ||
728 | process_one_v4_ace(&default_acl_state, ace); | ||
729 | |||
730 | if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE)) | ||
731 | process_one_v4_ace(&effective_acl_state, ace); | ||
736 | } | 732 | } |
737 | return 0; | 733 | *pacl = posix_state_to_acl(&effective_acl_state, flags); |
734 | if (IS_ERR(*pacl)) { | ||
735 | ret = PTR_ERR(*pacl); | ||
736 | goto out_dstate; | ||
737 | } | ||
738 | *dpacl = posix_state_to_acl(&default_acl_state, | ||
739 | flags | NFS4_ACL_TYPE_DEFAULT); | ||
740 | if (IS_ERR(*dpacl)) { | ||
741 | ret = PTR_ERR(*dpacl); | ||
742 | posix_acl_release(*pacl); | ||
743 | goto out_dstate; | ||
744 | } | ||
745 | sort_pacl(*pacl); | ||
746 | sort_pacl(*dpacl); | ||
747 | ret = 0; | ||
748 | out_dstate: | ||
749 | free_state(&default_acl_state); | ||
750 | out_estate: | ||
751 | free_state(&effective_acl_state); | ||
752 | return ret; | ||
738 | } | 753 | } |
739 | 754 | ||
740 | static short | 755 | static short |
@@ -759,48 +774,22 @@ EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4); | |||
759 | EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix); | 774 | EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix); |
760 | 775 | ||
761 | struct nfs4_acl * | 776 | struct nfs4_acl * |
762 | nfs4_acl_new(void) | 777 | nfs4_acl_new(int n) |
763 | { | 778 | { |
764 | struct nfs4_acl *acl; | 779 | struct nfs4_acl *acl; |
765 | 780 | ||
766 | if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL) | 781 | acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL); |
782 | if (acl == NULL) | ||
767 | return NULL; | 783 | return NULL; |
768 | |||
769 | acl->naces = 0; | 784 | acl->naces = 0; |
770 | INIT_LIST_HEAD(&acl->ace_head); | ||
771 | |||
772 | return acl; | 785 | return acl; |
773 | } | 786 | } |
774 | 787 | ||
775 | void | 788 | void |
776 | nfs4_acl_free(struct nfs4_acl *acl) | ||
777 | { | ||
778 | struct list_head *h; | ||
779 | struct nfs4_ace *ace; | ||
780 | |||
781 | if (!acl) | ||
782 | return; | ||
783 | |||
784 | while (!list_empty(&acl->ace_head)) { | ||
785 | h = acl->ace_head.next; | ||
786 | list_del(h); | ||
787 | ace = list_entry(h, struct nfs4_ace, l_ace); | ||
788 | kfree(ace); | ||
789 | } | ||
790 | |||
791 | kfree(acl); | ||
792 | |||
793 | return; | ||
794 | } | ||
795 | |||
796 | int | ||
797 | nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, | 789 | nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, |
798 | int whotype, uid_t who) | 790 | int whotype, uid_t who) |
799 | { | 791 | { |
800 | struct nfs4_ace *ace; | 792 | struct nfs4_ace *ace = acl->aces + acl->naces; |
801 | |||
802 | if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL) | ||
803 | return -ENOMEM; | ||
804 | 793 | ||
805 | ace->type = type; | 794 | ace->type = type; |
806 | ace->flag = flag; | 795 | ace->flag = flag; |
@@ -808,10 +797,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, | |||
808 | ace->whotype = whotype; | 797 | ace->whotype = whotype; |
809 | ace->who = who; | 798 | ace->who = who; |
810 | 799 | ||
811 | list_add_tail(&ace->l_ace, &acl->ace_head); | ||
812 | acl->naces++; | 800 | acl->naces++; |
813 | |||
814 | return 0; | ||
815 | } | 801 | } |
816 | 802 | ||
817 | static struct { | 803 | static struct { |
@@ -865,7 +851,6 @@ nfs4_acl_write_who(int who, char *p) | |||
865 | } | 851 | } |
866 | 852 | ||
867 | EXPORT_SYMBOL(nfs4_acl_new); | 853 | EXPORT_SYMBOL(nfs4_acl_new); |
868 | EXPORT_SYMBOL(nfs4_acl_free); | ||
869 | EXPORT_SYMBOL(nfs4_acl_add_ace); | 854 | EXPORT_SYMBOL(nfs4_acl_add_ace); |
870 | EXPORT_SYMBOL(nfs4_acl_get_whotype); | 855 | EXPORT_SYMBOL(nfs4_acl_get_whotype); |
871 | EXPORT_SYMBOL(nfs4_acl_write_who); | 856 | EXPORT_SYMBOL(nfs4_acl_write_who); |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index f57655a7a2b6..fb14d68eacab 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -387,7 +387,6 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
387 | .address = (struct sockaddr *)&addr, | 387 | .address = (struct sockaddr *)&addr, |
388 | .addrsize = sizeof(addr), | 388 | .addrsize = sizeof(addr), |
389 | .timeout = &timeparms, | 389 | .timeout = &timeparms, |
390 | .servername = clp->cl_name.data, | ||
391 | .program = program, | 390 | .program = program, |
392 | .version = nfs_cb_version[1]->number, | 391 | .version = nfs_cb_version[1]->number, |
393 | .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ | 392 | .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ |
@@ -397,6 +396,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
397 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], | 396 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], |
398 | .rpc_argp = clp, | 397 | .rpc_argp = clp, |
399 | }; | 398 | }; |
399 | char clientname[16]; | ||
400 | int status; | 400 | int status; |
401 | 401 | ||
402 | if (atomic_read(&cb->cb_set)) | 402 | if (atomic_read(&cb->cb_set)) |
@@ -419,6 +419,11 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
419 | memset(program->stats, 0, sizeof(cb->cb_stat)); | 419 | memset(program->stats, 0, sizeof(cb->cb_stat)); |
420 | program->stats->program = program; | 420 | program->stats->program = program; |
421 | 421 | ||
422 | /* Just here to make some printk's more useful: */ | ||
423 | snprintf(clientname, sizeof(clientname), | ||
424 | "%u.%u.%u.%u", NIPQUAD(addr.sin_addr)); | ||
425 | args.servername = clientname; | ||
426 | |||
422 | /* Create RPC client */ | 427 | /* Create RPC client */ |
423 | cb->cb_client = rpc_create(&args); | 428 | cb->cb_client = rpc_create(&args); |
424 | if (IS_ERR(cb->cb_client)) { | 429 | if (IS_ERR(cb->cb_client)) { |
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index b1902ebaab41..e4a83d727afd 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <linux/sunrpc/cache.h> | 50 | #include <linux/sunrpc/cache.h> |
51 | #include <linux/nfsd_idmap.h> | 51 | #include <linux/nfsd_idmap.h> |
52 | #include <linux/list.h> | 52 | #include <linux/list.h> |
53 | #include <linux/sched.h> | ||
54 | #include <linux/time.h> | 53 | #include <linux/time.h> |
55 | #include <linux/seq_file.h> | 54 | #include <linux/seq_file.h> |
56 | #include <linux/sunrpc/svcauth.h> | 55 | #include <linux/sunrpc/svcauth.h> |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9de89df961f4..9e4067999209 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -714,7 +714,7 @@ __be32 | |||
714 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 714 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
715 | struct nfsd4_setclientid *setclid) | 715 | struct nfsd4_setclientid *setclid) |
716 | { | 716 | { |
717 | __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; | 717 | struct sockaddr_in *sin = svc_addr_in(rqstp); |
718 | struct xdr_netobj clname = { | 718 | struct xdr_netobj clname = { |
719 | .len = setclid->se_namelen, | 719 | .len = setclid->se_namelen, |
720 | .data = setclid->se_name, | 720 | .data = setclid->se_name, |
@@ -749,7 +749,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
749 | */ | 749 | */ |
750 | status = nfserr_clid_inuse; | 750 | status = nfserr_clid_inuse; |
751 | if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred) | 751 | if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred) |
752 | || conf->cl_addr != ip_addr) { | 752 | || conf->cl_addr != sin->sin_addr.s_addr) { |
753 | printk("NFSD: setclientid: string in use by client" | 753 | printk("NFSD: setclientid: string in use by client" |
754 | "(clientid %08x/%08x)\n", | 754 | "(clientid %08x/%08x)\n", |
755 | conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id); | 755 | conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id); |
@@ -769,7 +769,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
769 | if (new == NULL) | 769 | if (new == NULL) |
770 | goto out; | 770 | goto out; |
771 | copy_verf(new, &clverifier); | 771 | copy_verf(new, &clverifier); |
772 | new->cl_addr = ip_addr; | 772 | new->cl_addr = sin->sin_addr.s_addr; |
773 | copy_cred(&new->cl_cred,&rqstp->rq_cred); | 773 | copy_cred(&new->cl_cred,&rqstp->rq_cred); |
774 | gen_clid(new); | 774 | gen_clid(new); |
775 | gen_confirm(new); | 775 | gen_confirm(new); |
@@ -801,7 +801,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
801 | if (new == NULL) | 801 | if (new == NULL) |
802 | goto out; | 802 | goto out; |
803 | copy_verf(new,&conf->cl_verifier); | 803 | copy_verf(new,&conf->cl_verifier); |
804 | new->cl_addr = ip_addr; | 804 | new->cl_addr = sin->sin_addr.s_addr; |
805 | copy_cred(&new->cl_cred,&rqstp->rq_cred); | 805 | copy_cred(&new->cl_cred,&rqstp->rq_cred); |
806 | copy_clid(new, conf); | 806 | copy_clid(new, conf); |
807 | gen_confirm(new); | 807 | gen_confirm(new); |
@@ -820,7 +820,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
820 | if (new == NULL) | 820 | if (new == NULL) |
821 | goto out; | 821 | goto out; |
822 | copy_verf(new,&clverifier); | 822 | copy_verf(new,&clverifier); |
823 | new->cl_addr = ip_addr; | 823 | new->cl_addr = sin->sin_addr.s_addr; |
824 | copy_cred(&new->cl_cred,&rqstp->rq_cred); | 824 | copy_cred(&new->cl_cred,&rqstp->rq_cred); |
825 | gen_clid(new); | 825 | gen_clid(new); |
826 | gen_confirm(new); | 826 | gen_confirm(new); |
@@ -847,7 +847,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
847 | if (new == NULL) | 847 | if (new == NULL) |
848 | goto out; | 848 | goto out; |
849 | copy_verf(new,&clverifier); | 849 | copy_verf(new,&clverifier); |
850 | new->cl_addr = ip_addr; | 850 | new->cl_addr = sin->sin_addr.s_addr; |
851 | copy_cred(&new->cl_cred,&rqstp->rq_cred); | 851 | copy_cred(&new->cl_cred,&rqstp->rq_cred); |
852 | gen_clid(new); | 852 | gen_clid(new); |
853 | gen_confirm(new); | 853 | gen_confirm(new); |
@@ -881,7 +881,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
881 | struct nfsd4_compound_state *cstate, | 881 | struct nfsd4_compound_state *cstate, |
882 | struct nfsd4_setclientid_confirm *setclientid_confirm) | 882 | struct nfsd4_setclientid_confirm *setclientid_confirm) |
883 | { | 883 | { |
884 | __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; | 884 | struct sockaddr_in *sin = svc_addr_in(rqstp); |
885 | struct nfs4_client *conf, *unconf; | 885 | struct nfs4_client *conf, *unconf; |
886 | nfs4_verifier confirm = setclientid_confirm->sc_confirm; | 886 | nfs4_verifier confirm = setclientid_confirm->sc_confirm; |
887 | clientid_t * clid = &setclientid_confirm->sc_clientid; | 887 | clientid_t * clid = &setclientid_confirm->sc_clientid; |
@@ -900,9 +900,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
900 | unconf = find_unconfirmed_client(clid); | 900 | unconf = find_unconfirmed_client(clid); |
901 | 901 | ||
902 | status = nfserr_clid_inuse; | 902 | status = nfserr_clid_inuse; |
903 | if (conf && conf->cl_addr != ip_addr) | 903 | if (conf && conf->cl_addr != sin->sin_addr.s_addr) |
904 | goto out; | 904 | goto out; |
905 | if (unconf && unconf->cl_addr != ip_addr) | 905 | if (unconf && unconf->cl_addr != sin->sin_addr.s_addr) |
906 | goto out; | 906 | goto out; |
907 | 907 | ||
908 | if ((conf && unconf) && | 908 | if ((conf && unconf) && |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 18aa9440df14..5d090f11f2be 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -199,24 +199,22 @@ defer_free(struct nfsd4_compoundargs *argp, | |||
199 | 199 | ||
200 | static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) | 200 | static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) |
201 | { | 201 | { |
202 | void *new = NULL; | ||
203 | if (p == argp->tmp) { | 202 | if (p == argp->tmp) { |
204 | new = kmalloc(nbytes, GFP_KERNEL); | 203 | p = kmalloc(nbytes, GFP_KERNEL); |
205 | if (!new) return NULL; | 204 | if (!p) |
206 | p = new; | 205 | return NULL; |
207 | memcpy(p, argp->tmp, nbytes); | 206 | memcpy(p, argp->tmp, nbytes); |
208 | } else { | 207 | } else { |
209 | BUG_ON(p != argp->tmpp); | 208 | BUG_ON(p != argp->tmpp); |
210 | argp->tmpp = NULL; | 209 | argp->tmpp = NULL; |
211 | } | 210 | } |
212 | if (defer_free(argp, kfree, p)) { | 211 | if (defer_free(argp, kfree, p)) { |
213 | kfree(new); | 212 | kfree(p); |
214 | return NULL; | 213 | return NULL; |
215 | } else | 214 | } else |
216 | return (char *)p; | 215 | return (char *)p; |
217 | } | 216 | } |
218 | 217 | ||
219 | |||
220 | static __be32 | 218 | static __be32 |
221 | nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) | 219 | nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) |
222 | { | 220 | { |
@@ -255,7 +253,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia | |||
255 | return status; | 253 | return status; |
256 | 254 | ||
257 | /* | 255 | /* |
258 | * According to spec, unsupported attributes return ERR_NOTSUPP; | 256 | * According to spec, unsupported attributes return ERR_ATTRNOTSUPP; |
259 | * read-only attributes return ERR_INVAL. | 257 | * read-only attributes return ERR_INVAL. |
260 | */ | 258 | */ |
261 | if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1)) | 259 | if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1)) |
@@ -273,42 +271,42 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia | |||
273 | iattr->ia_valid |= ATTR_SIZE; | 271 | iattr->ia_valid |= ATTR_SIZE; |
274 | } | 272 | } |
275 | if (bmval[0] & FATTR4_WORD0_ACL) { | 273 | if (bmval[0] & FATTR4_WORD0_ACL) { |
276 | int nace, i; | 274 | int nace; |
277 | struct nfs4_ace ace; | 275 | struct nfs4_ace *ace; |
278 | 276 | ||
279 | READ_BUF(4); len += 4; | 277 | READ_BUF(4); len += 4; |
280 | READ32(nace); | 278 | READ32(nace); |
281 | 279 | ||
282 | *acl = nfs4_acl_new(); | 280 | if (nace > NFS4_ACL_MAX) |
281 | return nfserr_resource; | ||
282 | |||
283 | *acl = nfs4_acl_new(nace); | ||
283 | if (*acl == NULL) { | 284 | if (*acl == NULL) { |
284 | host_err = -ENOMEM; | 285 | host_err = -ENOMEM; |
285 | goto out_nfserr; | 286 | goto out_nfserr; |
286 | } | 287 | } |
287 | defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl); | 288 | defer_free(argp, kfree, *acl); |
288 | 289 | ||
289 | for (i = 0; i < nace; i++) { | 290 | (*acl)->naces = nace; |
291 | for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) { | ||
290 | READ_BUF(16); len += 16; | 292 | READ_BUF(16); len += 16; |
291 | READ32(ace.type); | 293 | READ32(ace->type); |
292 | READ32(ace.flag); | 294 | READ32(ace->flag); |
293 | READ32(ace.access_mask); | 295 | READ32(ace->access_mask); |
294 | READ32(dummy32); | 296 | READ32(dummy32); |
295 | READ_BUF(dummy32); | 297 | READ_BUF(dummy32); |
296 | len += XDR_QUADLEN(dummy32) << 2; | 298 | len += XDR_QUADLEN(dummy32) << 2; |
297 | READMEM(buf, dummy32); | 299 | READMEM(buf, dummy32); |
298 | ace.whotype = nfs4_acl_get_whotype(buf, dummy32); | 300 | ace->whotype = nfs4_acl_get_whotype(buf, dummy32); |
299 | host_err = 0; | 301 | host_err = 0; |
300 | if (ace.whotype != NFS4_ACL_WHO_NAMED) | 302 | if (ace->whotype != NFS4_ACL_WHO_NAMED) |
301 | ace.who = 0; | 303 | ace->who = 0; |
302 | else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP) | 304 | else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) |
303 | host_err = nfsd_map_name_to_gid(argp->rqstp, | 305 | host_err = nfsd_map_name_to_gid(argp->rqstp, |
304 | buf, dummy32, &ace.who); | 306 | buf, dummy32, &ace->who); |
305 | else | 307 | else |
306 | host_err = nfsd_map_name_to_uid(argp->rqstp, | 308 | host_err = nfsd_map_name_to_uid(argp->rqstp, |
307 | buf, dummy32, &ace.who); | 309 | buf, dummy32, &ace->who); |
308 | if (host_err) | ||
309 | goto out_nfserr; | ||
310 | host_err = nfs4_acl_add_ace(*acl, ace.type, ace.flag, | ||
311 | ace.access_mask, ace.whotype, ace.who); | ||
312 | if (host_err) | 310 | if (host_err) |
313 | goto out_nfserr; | 311 | goto out_nfserr; |
314 | } | 312 | } |
@@ -1563,14 +1561,20 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1563 | if (exp->ex_fslocs.migrated) { | 1561 | if (exp->ex_fslocs.migrated) { |
1564 | WRITE64(NFS4_REFERRAL_FSID_MAJOR); | 1562 | WRITE64(NFS4_REFERRAL_FSID_MAJOR); |
1565 | WRITE64(NFS4_REFERRAL_FSID_MINOR); | 1563 | WRITE64(NFS4_REFERRAL_FSID_MINOR); |
1566 | } else if (is_fsid(fhp, rqstp->rq_reffh)) { | 1564 | } else switch(fsid_source(fhp)) { |
1565 | case FSIDSOURCE_FSID: | ||
1567 | WRITE64((u64)exp->ex_fsid); | 1566 | WRITE64((u64)exp->ex_fsid); |
1568 | WRITE64((u64)0); | 1567 | WRITE64((u64)0); |
1569 | } else { | 1568 | break; |
1569 | case FSIDSOURCE_DEV: | ||
1570 | WRITE32(0); | 1570 | WRITE32(0); |
1571 | WRITE32(MAJOR(stat.dev)); | 1571 | WRITE32(MAJOR(stat.dev)); |
1572 | WRITE32(0); | 1572 | WRITE32(0); |
1573 | WRITE32(MINOR(stat.dev)); | 1573 | WRITE32(MINOR(stat.dev)); |
1574 | break; | ||
1575 | case FSIDSOURCE_UUID: | ||
1576 | WRITEMEM(exp->ex_uuid, 16); | ||
1577 | break; | ||
1574 | } | 1578 | } |
1575 | } | 1579 | } |
1576 | if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) { | 1580 | if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) { |
@@ -1590,7 +1594,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1590 | } | 1594 | } |
1591 | if (bmval0 & FATTR4_WORD0_ACL) { | 1595 | if (bmval0 & FATTR4_WORD0_ACL) { |
1592 | struct nfs4_ace *ace; | 1596 | struct nfs4_ace *ace; |
1593 | struct list_head *h; | ||
1594 | 1597 | ||
1595 | if (acl == NULL) { | 1598 | if (acl == NULL) { |
1596 | if ((buflen -= 4) < 0) | 1599 | if ((buflen -= 4) < 0) |
@@ -1603,9 +1606,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1603 | goto out_resource; | 1606 | goto out_resource; |
1604 | WRITE32(acl->naces); | 1607 | WRITE32(acl->naces); |
1605 | 1608 | ||
1606 | list_for_each(h, &acl->ace_head) { | 1609 | for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { |
1607 | ace = list_entry(h, struct nfs4_ace, l_ace); | ||
1608 | |||
1609 | if ((buflen -= 4*3) < 0) | 1610 | if ((buflen -= 4*3) < 0) |
1610 | goto out_resource; | 1611 | goto out_resource; |
1611 | WRITE32(ace->type); | 1612 | WRITE32(ace->type); |
@@ -1815,7 +1816,7 @@ out_acl: | |||
1815 | status = nfs_ok; | 1816 | status = nfs_ok; |
1816 | 1817 | ||
1817 | out: | 1818 | out: |
1818 | nfs4_acl_free(acl); | 1819 | kfree(acl); |
1819 | if (fhp == &tempfh) | 1820 | if (fhp == &tempfh) |
1820 | fh_put(&tempfh); | 1821 | fh_put(&tempfh); |
1821 | return status; | 1822 | return status; |
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index f90d70475854..578f2c9d56be 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c | |||
@@ -185,7 +185,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type) | |||
185 | rp->c_state = RC_INPROG; | 185 | rp->c_state = RC_INPROG; |
186 | rp->c_xid = xid; | 186 | rp->c_xid = xid; |
187 | rp->c_proc = proc; | 187 | rp->c_proc = proc; |
188 | rp->c_addr = rqstp->rq_addr; | 188 | memcpy(&rp->c_addr, svc_addr_in(rqstp), sizeof(rp->c_addr)); |
189 | rp->c_prot = proto; | 189 | rp->c_prot = proto; |
190 | rp->c_vers = vers; | 190 | rp->c_vers = vers; |
191 | rp->c_timestamp = jiffies; | 191 | rp->c_timestamp = jiffies; |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index eedf2e3990a9..71c686dc7257 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -123,7 +123,7 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu | |||
123 | return PTR_ERR(data); | 123 | return PTR_ERR(data); |
124 | 124 | ||
125 | rv = write_op[ino](file, data, size); | 125 | rv = write_op[ino](file, data, size); |
126 | if (rv>0) { | 126 | if (rv >= 0) { |
127 | simple_transaction_set(file, rv); | 127 | simple_transaction_set(file, rv); |
128 | rv = size; | 128 | rv = size; |
129 | } | 129 | } |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index c59d6fbb7a6b..c2660cbfcd96 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -9,7 +9,6 @@ | |||
9 | * ... and again Southern-Winter 2001 to support export_operations | 9 | * ... and again Southern-Winter 2001 to support export_operations |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
14 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
15 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
@@ -20,6 +19,7 @@ | |||
20 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
21 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
22 | 21 | ||
22 | #include <linux/sunrpc/clnt.h> | ||
23 | #include <linux/sunrpc/svc.h> | 23 | #include <linux/sunrpc/svc.h> |
24 | #include <linux/nfsd/nfsd.h> | 24 | #include <linux/nfsd/nfsd.h> |
25 | 25 | ||
@@ -118,9 +118,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
118 | 118 | ||
119 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); | 119 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); |
120 | 120 | ||
121 | /* keep this filehandle for possible reference when encoding attributes */ | ||
122 | rqstp->rq_reffh = fh; | ||
123 | |||
124 | if (!fhp->fh_dentry) { | 121 | if (!fhp->fh_dentry) { |
125 | __u32 *datap=NULL; | 122 | __u32 *datap=NULL; |
126 | __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ | 123 | __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ |
@@ -145,10 +142,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
145 | } | 142 | } |
146 | len = key_len(fh->fh_fsid_type) / 4; | 143 | len = key_len(fh->fh_fsid_type) / 4; |
147 | if (len == 0) goto out; | 144 | if (len == 0) goto out; |
148 | if (fh->fh_fsid_type == 2) { | 145 | if (fh->fh_fsid_type == FSID_MAJOR_MINOR) { |
149 | /* deprecated, convert to type 3 */ | 146 | /* deprecated, convert to type 3 */ |
150 | len = 3; | 147 | len = key_len(FSID_ENCODE_DEV)/4; |
151 | fh->fh_fsid_type = 3; | 148 | fh->fh_fsid_type = FSID_ENCODE_DEV; |
152 | fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1]))); | 149 | fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1]))); |
153 | fh->fh_fsid[1] = fh->fh_fsid[2]; | 150 | fh->fh_fsid[1] = fh->fh_fsid[2]; |
154 | } | 151 | } |
@@ -163,8 +160,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
163 | /* assume old filehandle format */ | 160 | /* assume old filehandle format */ |
164 | xdev = old_decode_dev(fh->ofh_xdev); | 161 | xdev = old_decode_dev(fh->ofh_xdev); |
165 | xino = u32_to_ino_t(fh->ofh_xino); | 162 | xino = u32_to_ino_t(fh->ofh_xino); |
166 | mk_fsid_v0(tfh, xdev, xino); | 163 | mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL); |
167 | exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle); | 164 | exp = exp_find(rqstp->rq_client, FSID_DEV, tfh, |
165 | &rqstp->rq_chandle); | ||
168 | } | 166 | } |
169 | 167 | ||
170 | if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN | 168 | if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN |
@@ -180,10 +178,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
180 | /* Check if the request originated from a secure port. */ | 178 | /* Check if the request originated from a secure port. */ |
181 | error = nfserr_perm; | 179 | error = nfserr_perm; |
182 | if (!rqstp->rq_secure && EX_SECURE(exp)) { | 180 | if (!rqstp->rq_secure && EX_SECURE(exp)) { |
181 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
183 | printk(KERN_WARNING | 182 | printk(KERN_WARNING |
184 | "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n", | 183 | "nfsd: request from insecure port %s!\n", |
185 | NIPQUAD(rqstp->rq_addr.sin_addr.s_addr), | 184 | svc_print_addr(rqstp, buf, sizeof(buf))); |
186 | ntohs(rqstp->rq_addr.sin_port)); | ||
187 | goto out; | 185 | goto out; |
188 | } | 186 | } |
189 | 187 | ||
@@ -211,7 +209,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
211 | fileid_type = 2; | 209 | fileid_type = 2; |
212 | } else | 210 | } else |
213 | fileid_type = fh->fh_fileid_type; | 211 | fileid_type = fh->fh_fileid_type; |
214 | 212 | ||
215 | if (fileid_type == 0) | 213 | if (fileid_type == 0) |
216 | dentry = dget(exp->ex_dentry); | 214 | dentry = dget(exp->ex_dentry); |
217 | else { | 215 | else { |
@@ -291,7 +289,7 @@ static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, | |||
291 | __u32 *datap, int *maxsize) | 289 | __u32 *datap, int *maxsize) |
292 | { | 290 | { |
293 | struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op; | 291 | struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op; |
294 | 292 | ||
295 | if (dentry == exp->ex_dentry) { | 293 | if (dentry == exp->ex_dentry) { |
296 | *maxsize = 0; | 294 | *maxsize = 0; |
297 | return 0; | 295 | return 0; |
@@ -316,7 +314,8 @@ static inline void _fh_update_old(struct dentry *dentry, | |||
316 | } | 314 | } |
317 | 315 | ||
318 | __be32 | 316 | __be32 |
319 | fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) | 317 | fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, |
318 | struct svc_fh *ref_fh) | ||
320 | { | 319 | { |
321 | /* ref_fh is a reference file handle. | 320 | /* ref_fh is a reference file handle. |
322 | * if it is non-null and for the same filesystem, then we should compose | 321 | * if it is non-null and for the same filesystem, then we should compose |
@@ -326,12 +325,13 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st | |||
326 | * | 325 | * |
327 | */ | 326 | */ |
328 | 327 | ||
329 | u8 ref_fh_version = 0; | 328 | u8 version = 1; |
330 | u8 ref_fh_fsid_type = 0; | 329 | u8 fsid_type = 0; |
331 | struct inode * inode = dentry->d_inode; | 330 | struct inode * inode = dentry->d_inode; |
332 | struct dentry *parent = dentry->d_parent; | 331 | struct dentry *parent = dentry->d_parent; |
333 | __u32 *datap; | 332 | __u32 *datap; |
334 | dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev; | 333 | dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev; |
334 | int root_export = (exp->ex_dentry == exp->ex_dentry->d_sb->s_root); | ||
335 | 335 | ||
336 | dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", | 336 | dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", |
337 | MAJOR(ex_dev), MINOR(ex_dev), | 337 | MAJOR(ex_dev), MINOR(ex_dev), |
@@ -339,57 +339,64 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st | |||
339 | parent->d_name.name, dentry->d_name.name, | 339 | parent->d_name.name, dentry->d_name.name, |
340 | (inode ? inode->i_ino : 0)); | 340 | (inode ? inode->i_ino : 0)); |
341 | 341 | ||
342 | /* Choose filehandle version and fsid type based on | ||
343 | * the reference filehandle (if it is in the same export) | ||
344 | * or the export options. | ||
345 | */ | ||
342 | if (ref_fh && ref_fh->fh_export == exp) { | 346 | if (ref_fh && ref_fh->fh_export == exp) { |
343 | ref_fh_version = ref_fh->fh_handle.fh_version; | 347 | version = ref_fh->fh_handle.fh_version; |
344 | if (ref_fh_version == 0xca) | 348 | if (version == 0xca) |
345 | ref_fh_fsid_type = 0; | 349 | fsid_type = FSID_DEV; |
346 | else | 350 | else |
347 | ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type; | 351 | fsid_type = ref_fh->fh_handle.fh_fsid_type; |
348 | if (ref_fh_fsid_type > 3) | 352 | /* We know this version/type works for this export |
349 | ref_fh_fsid_type = 0; | 353 | * so there is no need for further checks. |
350 | 354 | */ | |
351 | /* make sure ref_fh type works for given export */ | 355 | } else if (exp->ex_uuid) { |
352 | if (ref_fh_fsid_type == 1 && | 356 | if (fhp->fh_maxsize >= 64) { |
353 | !(exp->ex_flags & NFSEXP_FSID)) { | 357 | if (root_export) |
354 | /* if we don't have an fsid, we cannot provide one... */ | 358 | fsid_type = FSID_UUID16; |
355 | ref_fh_fsid_type = 0; | 359 | else |
360 | fsid_type = FSID_UUID16_INUM; | ||
361 | } else { | ||
362 | if (root_export) | ||
363 | fsid_type = FSID_UUID8; | ||
364 | else | ||
365 | fsid_type = FSID_UUID4_INUM; | ||
356 | } | 366 | } |
357 | } else if (exp->ex_flags & NFSEXP_FSID) | 367 | } else if (exp->ex_flags & NFSEXP_FSID) |
358 | ref_fh_fsid_type = 1; | 368 | fsid_type = FSID_NUM; |
359 | 369 | else if (!old_valid_dev(ex_dev)) | |
360 | if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) { | ||
361 | /* for newer device numbers, we must use a newer fsid format */ | 370 | /* for newer device numbers, we must use a newer fsid format */ |
362 | ref_fh_version = 1; | 371 | fsid_type = FSID_ENCODE_DEV; |
363 | ref_fh_fsid_type = 3; | 372 | else |
364 | } | 373 | fsid_type = FSID_DEV; |
365 | if (old_valid_dev(ex_dev) && | ||
366 | (ref_fh_fsid_type == 2 || ref_fh_fsid_type == 3)) | ||
367 | /* must use type1 for smaller device numbers */ | ||
368 | ref_fh_fsid_type = 0; | ||
369 | 374 | ||
370 | if (ref_fh == fhp) | 375 | if (ref_fh == fhp) |
371 | fh_put(ref_fh); | 376 | fh_put(ref_fh); |
372 | 377 | ||
373 | if (fhp->fh_locked || fhp->fh_dentry) { | 378 | if (fhp->fh_locked || fhp->fh_dentry) { |
374 | printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", | 379 | printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", |
375 | parent->d_name.name, dentry->d_name.name); | 380 | parent->d_name.name, dentry->d_name.name); |
376 | } | 381 | } |
377 | if (fhp->fh_maxsize < NFS_FHSIZE) | 382 | if (fhp->fh_maxsize < NFS_FHSIZE) |
378 | printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n", | 383 | printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n", |
379 | fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name); | 384 | fhp->fh_maxsize, |
385 | parent->d_name.name, dentry->d_name.name); | ||
380 | 386 | ||
381 | fhp->fh_dentry = dget(dentry); /* our internal copy */ | 387 | fhp->fh_dentry = dget(dentry); /* our internal copy */ |
382 | fhp->fh_export = exp; | 388 | fhp->fh_export = exp; |
383 | cache_get(&exp->h); | 389 | cache_get(&exp->h); |
384 | 390 | ||
385 | if (ref_fh_version == 0xca) { | 391 | if (version == 0xca) { |
386 | /* old style filehandle please */ | 392 | /* old style filehandle please */ |
387 | memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); | 393 | memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); |
388 | fhp->fh_handle.fh_size = NFS_FHSIZE; | 394 | fhp->fh_handle.fh_size = NFS_FHSIZE; |
389 | fhp->fh_handle.ofh_dcookie = 0xfeebbaca; | 395 | fhp->fh_handle.ofh_dcookie = 0xfeebbaca; |
390 | fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); | 396 | fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); |
391 | fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; | 397 | fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; |
392 | fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino); | 398 | fhp->fh_handle.ofh_xino = |
399 | ino_t_to_u32(exp->ex_dentry->d_inode->i_ino); | ||
393 | fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); | 400 | fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); |
394 | if (inode) | 401 | if (inode) |
395 | _fh_update_old(dentry, exp, &fhp->fh_handle); | 402 | _fh_update_old(dentry, exp, &fhp->fh_handle); |
@@ -398,38 +405,12 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st | |||
398 | fhp->fh_handle.fh_version = 1; | 405 | fhp->fh_handle.fh_version = 1; |
399 | fhp->fh_handle.fh_auth_type = 0; | 406 | fhp->fh_handle.fh_auth_type = 0; |
400 | datap = fhp->fh_handle.fh_auth+0; | 407 | datap = fhp->fh_handle.fh_auth+0; |
401 | fhp->fh_handle.fh_fsid_type = ref_fh_fsid_type; | 408 | fhp->fh_handle.fh_fsid_type = fsid_type; |
402 | switch (ref_fh_fsid_type) { | 409 | mk_fsid(fsid_type, datap, ex_dev, |
403 | case 0: | 410 | exp->ex_dentry->d_inode->i_ino, |
404 | /* | 411 | exp->ex_fsid, exp->ex_uuid); |
405 | * fsid_type 0: | 412 | |
406 | * 2byte major, 2byte minor, 4byte inode | 413 | len = key_len(fsid_type); |
407 | */ | ||
408 | mk_fsid_v0(datap, ex_dev, | ||
409 | exp->ex_dentry->d_inode->i_ino); | ||
410 | break; | ||
411 | case 1: | ||
412 | /* fsid_type 1 == 4 bytes filesystem id */ | ||
413 | mk_fsid_v1(datap, exp->ex_fsid); | ||
414 | break; | ||
415 | case 2: | ||
416 | /* | ||
417 | * fsid_type 2: | ||
418 | * 4byte major, 4byte minor, 4byte inode | ||
419 | */ | ||
420 | mk_fsid_v2(datap, ex_dev, | ||
421 | exp->ex_dentry->d_inode->i_ino); | ||
422 | break; | ||
423 | case 3: | ||
424 | /* | ||
425 | * fsid_type 3: | ||
426 | * 4byte devicenumber, 4byte inode | ||
427 | */ | ||
428 | mk_fsid_v3(datap, ex_dev, | ||
429 | exp->ex_dentry->d_inode->i_ino); | ||
430 | break; | ||
431 | } | ||
432 | len = key_len(ref_fh_fsid_type); | ||
433 | datap += len/4; | 414 | datap += len/4; |
434 | fhp->fh_handle.fh_size = 4 + len; | 415 | fhp->fh_handle.fh_size = 4 + len; |
435 | 416 | ||
@@ -456,7 +437,7 @@ fh_update(struct svc_fh *fhp) | |||
456 | { | 437 | { |
457 | struct dentry *dentry; | 438 | struct dentry *dentry; |
458 | __u32 *datap; | 439 | __u32 *datap; |
459 | 440 | ||
460 | if (!fhp->fh_dentry) | 441 | if (!fhp->fh_dentry) |
461 | goto out_bad; | 442 | goto out_bad; |
462 | 443 | ||
@@ -533,3 +514,22 @@ char * SVCFH_fmt(struct svc_fh *fhp) | |||
533 | fh->fh_base.fh_pad[5]); | 514 | fh->fh_base.fh_pad[5]); |
534 | return buf; | 515 | return buf; |
535 | } | 516 | } |
517 | |||
518 | enum fsid_source fsid_source(struct svc_fh *fhp) | ||
519 | { | ||
520 | if (fhp->fh_handle.fh_version != 1) | ||
521 | return FSIDSOURCE_DEV; | ||
522 | switch(fhp->fh_handle.fh_fsid_type) { | ||
523 | case FSID_DEV: | ||
524 | case FSID_ENCODE_DEV: | ||
525 | case FSID_MAJOR_MINOR: | ||
526 | return FSIDSOURCE_DEV; | ||
527 | case FSID_NUM: | ||
528 | return FSIDSOURCE_FSID; | ||
529 | default: | ||
530 | if (fhp->fh_export->ex_flags & NFSEXP_FSID) | ||
531 | return FSIDSOURCE_FSID; | ||
532 | else | ||
533 | return FSIDSOURCE_UUID; | ||
534 | } | ||
535 | } | ||
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index ec983b777680..5cc2eec981b8 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/unistd.h> | 19 | #include <linux/unistd.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | 21 | ||
22 | #include <linux/sunrpc/clnt.h> | ||
22 | #include <linux/sunrpc/svc.h> | 23 | #include <linux/sunrpc/svc.h> |
23 | #include <linux/nfsd/nfsd.h> | 24 | #include <linux/nfsd/nfsd.h> |
24 | #include <linux/nfsd/cache.h> | 25 | #include <linux/nfsd/cache.h> |
@@ -147,10 +148,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, | |||
147 | */ | 148 | */ |
148 | 149 | ||
149 | if (NFSSVC_MAXBLKSIZE_V2 < argp->count) { | 150 | if (NFSSVC_MAXBLKSIZE_V2 < argp->count) { |
151 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
150 | printk(KERN_NOTICE | 152 | printk(KERN_NOTICE |
151 | "oversized read request from %u.%u.%u.%u:%d (%d bytes)\n", | 153 | "oversized read request from %s (%d bytes)\n", |
152 | NIPQUAD(rqstp->rq_addr.sin_addr.s_addr), | 154 | svc_print_addr(rqstp, buf, sizeof(buf)), |
153 | ntohs(rqstp->rq_addr.sin_port), | ||
154 | argp->count); | 155 | argp->count); |
155 | argp->count = NFSSVC_MAXBLKSIZE_V2; | 156 | argp->count = NFSSVC_MAXBLKSIZE_V2; |
156 | } | 157 | } |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index fbf5d51947ea..d7759ce6ed94 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -235,7 +235,8 @@ static int nfsd_init_socks(int port) | |||
235 | 235 | ||
236 | error = lockd_up(IPPROTO_UDP); | 236 | error = lockd_up(IPPROTO_UDP); |
237 | if (error >= 0) { | 237 | if (error >= 0) { |
238 | error = svc_makesock(nfsd_serv, IPPROTO_UDP, port); | 238 | error = svc_makesock(nfsd_serv, IPPROTO_UDP, port, |
239 | SVC_SOCK_DEFAULTS); | ||
239 | if (error < 0) | 240 | if (error < 0) |
240 | lockd_down(); | 241 | lockd_down(); |
241 | } | 242 | } |
@@ -245,7 +246,8 @@ static int nfsd_init_socks(int port) | |||
245 | #ifdef CONFIG_NFSD_TCP | 246 | #ifdef CONFIG_NFSD_TCP |
246 | error = lockd_up(IPPROTO_TCP); | 247 | error = lockd_up(IPPROTO_TCP); |
247 | if (error >= 0) { | 248 | if (error >= 0) { |
248 | error = svc_makesock(nfsd_serv, IPPROTO_TCP, port); | 249 | error = svc_makesock(nfsd_serv, IPPROTO_TCP, port, |
250 | SVC_SOCK_DEFAULTS); | ||
249 | if (error < 0) | 251 | if (error < 0) |
250 | lockd_down(); | 252 | lockd_down(); |
251 | } | 253 | } |
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 6555c50d9006..0c24b9e24fe8 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
@@ -153,6 +153,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
153 | struct dentry *dentry = fhp->fh_dentry; | 153 | struct dentry *dentry = fhp->fh_dentry; |
154 | int type; | 154 | int type; |
155 | struct timespec time; | 155 | struct timespec time; |
156 | u32 f; | ||
156 | 157 | ||
157 | type = (stat->mode & S_IFMT); | 158 | type = (stat->mode & S_IFMT); |
158 | 159 | ||
@@ -173,10 +174,22 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
173 | else | 174 | else |
174 | *p++ = htonl(0xffffffff); | 175 | *p++ = htonl(0xffffffff); |
175 | *p++ = htonl((u32) stat->blocks); | 176 | *p++ = htonl((u32) stat->blocks); |
176 | if (is_fsid(fhp, rqstp->rq_reffh)) | 177 | switch (fsid_source(fhp)) { |
177 | *p++ = htonl((u32) fhp->fh_export->ex_fsid); | 178 | default: |
178 | else | 179 | case FSIDSOURCE_DEV: |
179 | *p++ = htonl(new_encode_dev(stat->dev)); | 180 | *p++ = htonl(new_encode_dev(stat->dev)); |
181 | break; | ||
182 | case FSIDSOURCE_FSID: | ||
183 | *p++ = htonl((u32) fhp->fh_export->ex_fsid); | ||
184 | break; | ||
185 | case FSIDSOURCE_UUID: | ||
186 | f = ((u32*)fhp->fh_export->ex_uuid)[0]; | ||
187 | f ^= ((u32*)fhp->fh_export->ex_uuid)[1]; | ||
188 | f ^= ((u32*)fhp->fh_export->ex_uuid)[2]; | ||
189 | f ^= ((u32*)fhp->fh_export->ex_uuid)[3]; | ||
190 | *p++ = htonl(f); | ||
191 | break; | ||
192 | } | ||
180 | *p++ = htonl((u32) stat->ino); | 193 | *p++ = htonl((u32) stat->ino); |
181 | *p++ = htonl((u32) stat->atime.tv_sec); | 194 | *p++ = htonl((u32) stat->atime.tv_sec); |
182 | *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0); | 195 | *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 8283236c6a0f..7e6aa245b5d5 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -466,7 +466,10 @@ out: | |||
466 | posix_acl_release(dpacl); | 466 | posix_acl_release(dpacl); |
467 | return (error); | 467 | return (error); |
468 | out_nfserr: | 468 | out_nfserr: |
469 | error = nfserrno(host_error); | 469 | if (host_error == -EOPNOTSUPP) |
470 | error = nfserr_attrnotsupp; | ||
471 | else | ||
472 | error = nfserrno(host_error); | ||
470 | goto out; | 473 | goto out; |
471 | } | 474 | } |
472 | 475 | ||
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index c577d8e1bd95..7659cc192995 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -1921,7 +1921,7 @@ s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size, | |||
1921 | u32 attr_len = 0; /* Silence stupid gcc warning. */ | 1921 | u32 attr_len = 0; /* Silence stupid gcc warning. */ |
1922 | bool mp_rebuilt; | 1922 | bool mp_rebuilt; |
1923 | 1923 | ||
1924 | #ifdef NTFS_DEBUG | 1924 | #ifdef DEBUG |
1925 | read_lock_irqsave(&ni->size_lock, flags); | 1925 | read_lock_irqsave(&ni->size_lock, flags); |
1926 | allocated_size = ni->allocated_size; | 1926 | allocated_size = ni->allocated_size; |
1927 | read_unlock_irqrestore(&ni->size_lock, flags); | 1927 | read_unlock_irqrestore(&ni->size_lock, flags); |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 076c9420c257..d69c4595ccd0 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -2328,7 +2328,7 @@ const struct file_operations ntfs_file_ops = { | |||
2328 | the data source. */ | 2328 | the data source. */ |
2329 | }; | 2329 | }; |
2330 | 2330 | ||
2331 | struct inode_operations ntfs_file_inode_ops = { | 2331 | const struct inode_operations ntfs_file_inode_ops = { |
2332 | #ifdef NTFS_RW | 2332 | #ifdef NTFS_RW |
2333 | .truncate = ntfs_truncate_vfs, | 2333 | .truncate = ntfs_truncate_vfs, |
2334 | .setattr = ntfs_setattr, | 2334 | .setattr = ntfs_setattr, |
@@ -2337,4 +2337,4 @@ struct inode_operations ntfs_file_inode_ops = { | |||
2337 | 2337 | ||
2338 | const struct file_operations ntfs_empty_file_ops = {}; | 2338 | const struct file_operations ntfs_empty_file_ops = {}; |
2339 | 2339 | ||
2340 | struct inode_operations ntfs_empty_inode_ops = {}; | 2340 | const struct inode_operations ntfs_empty_inode_ops = {}; |
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index eddb2247cec5..bff01a54675a 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c | |||
@@ -359,7 +359,7 @@ err_out: | |||
359 | /** | 359 | /** |
360 | * Inode operations for directories. | 360 | * Inode operations for directories. |
361 | */ | 361 | */ |
362 | struct inode_operations ntfs_dir_inode_ops = { | 362 | const struct inode_operations ntfs_dir_inode_ops = { |
363 | .lookup = ntfs_lookup, /* VFS: Lookup directory. */ | 363 | .lookup = ntfs_lookup, /* VFS: Lookup directory. */ |
364 | }; | 364 | }; |
365 | 365 | ||
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index a12847ae467d..d73f5a9ac341 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h | |||
@@ -61,13 +61,13 @@ extern const struct address_space_operations ntfs_aops; | |||
61 | extern const struct address_space_operations ntfs_mst_aops; | 61 | extern const struct address_space_operations ntfs_mst_aops; |
62 | 62 | ||
63 | extern const struct file_operations ntfs_file_ops; | 63 | extern const struct file_operations ntfs_file_ops; |
64 | extern struct inode_operations ntfs_file_inode_ops; | 64 | extern const struct inode_operations ntfs_file_inode_ops; |
65 | 65 | ||
66 | extern const struct file_operations ntfs_dir_ops; | 66 | extern const struct file_operations ntfs_dir_ops; |
67 | extern struct inode_operations ntfs_dir_inode_ops; | 67 | extern const struct inode_operations ntfs_dir_inode_ops; |
68 | 68 | ||
69 | extern const struct file_operations ntfs_empty_file_ops; | 69 | extern const struct file_operations ntfs_empty_file_ops; |
70 | extern struct inode_operations ntfs_empty_inode_ops; | 70 | extern const struct inode_operations ntfs_empty_inode_ops; |
71 | 71 | ||
72 | extern struct export_operations ntfs_export_ops; | 72 | extern struct export_operations ntfs_export_ops; |
73 | 73 | ||
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index babf94d90def..1594c90b7164 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c | |||
@@ -2699,7 +2699,7 @@ static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs) | |||
2699 | /** | 2699 | /** |
2700 | * The complete super operations. | 2700 | * The complete super operations. |
2701 | */ | 2701 | */ |
2702 | static struct super_operations ntfs_sops = { | 2702 | static const struct super_operations ntfs_sops = { |
2703 | .alloc_inode = ntfs_alloc_big_inode, /* VFS: Allocate new inode. */ | 2703 | .alloc_inode = ntfs_alloc_big_inode, /* VFS: Allocate new inode. */ |
2704 | .destroy_inode = ntfs_destroy_big_inode, /* VFS: Deallocate inode. */ | 2704 | .destroy_inode = ntfs_destroy_big_inode, /* VFS: Deallocate inode. */ |
2705 | #ifdef NTFS_RW | 2705 | #ifdef NTFS_RW |
diff --git a/fs/ntfs/sysctl.c b/fs/ntfs/sysctl.c index 1c23138d00b3..4847fbfb0107 100644 --- a/fs/ntfs/sysctl.c +++ b/fs/ntfs/sysctl.c | |||
@@ -33,20 +33,28 @@ | |||
33 | #include "sysctl.h" | 33 | #include "sysctl.h" |
34 | #include "debug.h" | 34 | #include "debug.h" |
35 | 35 | ||
36 | #define FS_NTFS 1 | ||
37 | |||
38 | /* Definition of the ntfs sysctl. */ | 36 | /* Definition of the ntfs sysctl. */ |
39 | static ctl_table ntfs_sysctls[] = { | 37 | static ctl_table ntfs_sysctls[] = { |
40 | { FS_NTFS, "ntfs-debug", /* Binary and text IDs. */ | 38 | { |
41 | &debug_msgs,sizeof(debug_msgs), /* Data pointer and size. */ | 39 | .ctl_name = CTL_UNNUMBERED, /* Binary and text IDs. */ |
42 | 0644, NULL, &proc_dointvec }, /* Mode, child, proc handler. */ | 40 | .procname = "ntfs-debug", |
43 | { 0 } | 41 | .data = &debug_msgs, /* Data pointer and size. */ |
42 | .maxlen = sizeof(debug_msgs), | ||
43 | .mode = 0644, /* Mode, proc handler. */ | ||
44 | .proc_handler = &proc_dointvec | ||
45 | }, | ||
46 | {} | ||
44 | }; | 47 | }; |
45 | 48 | ||
46 | /* Define the parent directory /proc/sys/fs. */ | 49 | /* Define the parent directory /proc/sys/fs. */ |
47 | static ctl_table sysctls_root[] = { | 50 | static ctl_table sysctls_root[] = { |
48 | { CTL_FS, "fs", NULL, 0, 0555, ntfs_sysctls }, | 51 | { |
49 | { 0 } | 52 | .ctl_name = CTL_FS, |
53 | .procname = "fs", | ||
54 | .mode = 0555, | ||
55 | .child = ntfs_sysctls | ||
56 | }, | ||
57 | {} | ||
50 | }; | 58 | }; |
51 | 59 | ||
52 | /* Storage for the sysctls header. */ | 60 | /* Storage for the sysctls header. */ |
@@ -62,17 +70,9 @@ int ntfs_sysctl(int add) | |||
62 | { | 70 | { |
63 | if (add) { | 71 | if (add) { |
64 | BUG_ON(sysctls_root_table); | 72 | BUG_ON(sysctls_root_table); |
65 | sysctls_root_table = register_sysctl_table(sysctls_root, 0); | 73 | sysctls_root_table = register_sysctl_table(sysctls_root); |
66 | if (!sysctls_root_table) | 74 | if (!sysctls_root_table) |
67 | return -ENOMEM; | 75 | return -ENOMEM; |
68 | #ifdef CONFIG_PROC_FS | ||
69 | /* | ||
70 | * If the proc filesystem is in use and we are a module, need | ||
71 | * to set the owner of our proc entry to our module. In the | ||
72 | * non-modular case, THIS_MODULE is NULL, so this is ok. | ||
73 | */ | ||
74 | ntfs_sysctls[0].de->owner = THIS_MODULE; | ||
75 | #endif | ||
76 | } else { | 76 | } else { |
77 | BUG_ON(!sysctls_root_table); | 77 | BUG_ON(!sysctls_root_table); |
78 | unregister_sysctl_table(sysctls_root_table); | 78 | unregister_sysctl_table(sysctls_root_table); |
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c index b17333a0606b..9f5ad0f01ce0 100644 --- a/fs/ocfs2/cluster/nodemanager.c +++ b/fs/ocfs2/cluster/nodemanager.c | |||
@@ -55,7 +55,7 @@ static ctl_table ocfs2_nm_table[] = { | |||
55 | 55 | ||
56 | static ctl_table ocfs2_mod_table[] = { | 56 | static ctl_table ocfs2_mod_table[] = { |
57 | { | 57 | { |
58 | .ctl_name = KERN_OCFS2_NM, | 58 | .ctl_name = FS_OCFS2_NM, |
59 | .procname = "nm", | 59 | .procname = "nm", |
60 | .data = NULL, | 60 | .data = NULL, |
61 | .maxlen = 0, | 61 | .maxlen = 0, |
@@ -67,7 +67,7 @@ static ctl_table ocfs2_mod_table[] = { | |||
67 | 67 | ||
68 | static ctl_table ocfs2_kern_table[] = { | 68 | static ctl_table ocfs2_kern_table[] = { |
69 | { | 69 | { |
70 | .ctl_name = KERN_OCFS2, | 70 | .ctl_name = FS_OCFS2, |
71 | .procname = "ocfs2", | 71 | .procname = "ocfs2", |
72 | .data = NULL, | 72 | .data = NULL, |
73 | .maxlen = 0, | 73 | .maxlen = 0, |
@@ -922,7 +922,7 @@ static int __init init_o2nm(void) | |||
922 | o2hb_init(); | 922 | o2hb_init(); |
923 | o2net_init(); | 923 | o2net_init(); |
924 | 924 | ||
925 | ocfs2_table_header = register_sysctl_table(ocfs2_root_table, 0); | 925 | ocfs2_table_header = register_sysctl_table(ocfs2_root_table); |
926 | if (!ocfs2_table_header) { | 926 | if (!ocfs2_table_header) { |
927 | printk(KERN_ERR "nodemanager: unable to register sysctl\n"); | 927 | printk(KERN_ERR "nodemanager: unable to register sysctl\n"); |
928 | ret = -ENOMEM; /* or something. */ | 928 | ret = -ENOMEM; /* or something. */ |
diff --git a/fs/ocfs2/cluster/nodemanager.h b/fs/ocfs2/cluster/nodemanager.h index 8fb23cacc2f5..070522138ae2 100644 --- a/fs/ocfs2/cluster/nodemanager.h +++ b/fs/ocfs2/cluster/nodemanager.h | |||
@@ -33,8 +33,7 @@ | |||
33 | #include <linux/configfs.h> | 33 | #include <linux/configfs.h> |
34 | #include <linux/rbtree.h> | 34 | #include <linux/rbtree.h> |
35 | 35 | ||
36 | #define KERN_OCFS2 988 | 36 | #define FS_OCFS2_NM 1 |
37 | #define KERN_OCFS2_NM 1 | ||
38 | 37 | ||
39 | const char *o2nm_get_hb_ctl_path(void); | 38 | const char *o2nm_get_hb_ctl_path(void); |
40 | 39 | ||
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index b7f0ba97a1a2..de952eba29a9 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c | |||
@@ -61,11 +61,11 @@ | |||
61 | #define MLOG_MASK_PREFIX ML_DLMFS | 61 | #define MLOG_MASK_PREFIX ML_DLMFS |
62 | #include "cluster/masklog.h" | 62 | #include "cluster/masklog.h" |
63 | 63 | ||
64 | static struct super_operations dlmfs_ops; | 64 | static const struct super_operations dlmfs_ops; |
65 | static struct file_operations dlmfs_file_operations; | 65 | static const struct file_operations dlmfs_file_operations; |
66 | static struct inode_operations dlmfs_dir_inode_operations; | 66 | static const struct inode_operations dlmfs_dir_inode_operations; |
67 | static struct inode_operations dlmfs_root_inode_operations; | 67 | static const struct inode_operations dlmfs_root_inode_operations; |
68 | static struct inode_operations dlmfs_file_inode_operations; | 68 | static const struct inode_operations dlmfs_file_inode_operations; |
69 | static struct kmem_cache *dlmfs_inode_cache; | 69 | static struct kmem_cache *dlmfs_inode_cache; |
70 | 70 | ||
71 | struct workqueue_struct *user_dlm_worker; | 71 | struct workqueue_struct *user_dlm_worker; |
@@ -540,27 +540,27 @@ static int dlmfs_fill_super(struct super_block * sb, | |||
540 | return 0; | 540 | return 0; |
541 | } | 541 | } |
542 | 542 | ||
543 | static struct file_operations dlmfs_file_operations = { | 543 | static const struct file_operations dlmfs_file_operations = { |
544 | .open = dlmfs_file_open, | 544 | .open = dlmfs_file_open, |
545 | .release = dlmfs_file_release, | 545 | .release = dlmfs_file_release, |
546 | .read = dlmfs_file_read, | 546 | .read = dlmfs_file_read, |
547 | .write = dlmfs_file_write, | 547 | .write = dlmfs_file_write, |
548 | }; | 548 | }; |
549 | 549 | ||
550 | static struct inode_operations dlmfs_dir_inode_operations = { | 550 | static const struct inode_operations dlmfs_dir_inode_operations = { |
551 | .create = dlmfs_create, | 551 | .create = dlmfs_create, |
552 | .lookup = simple_lookup, | 552 | .lookup = simple_lookup, |
553 | .unlink = dlmfs_unlink, | 553 | .unlink = dlmfs_unlink, |
554 | }; | 554 | }; |
555 | 555 | ||
556 | /* this way we can restrict mkdir to only the toplevel of the fs. */ | 556 | /* this way we can restrict mkdir to only the toplevel of the fs. */ |
557 | static struct inode_operations dlmfs_root_inode_operations = { | 557 | static const struct inode_operations dlmfs_root_inode_operations = { |
558 | .lookup = simple_lookup, | 558 | .lookup = simple_lookup, |
559 | .mkdir = dlmfs_mkdir, | 559 | .mkdir = dlmfs_mkdir, |
560 | .rmdir = simple_rmdir, | 560 | .rmdir = simple_rmdir, |
561 | }; | 561 | }; |
562 | 562 | ||
563 | static struct super_operations dlmfs_ops = { | 563 | static const struct super_operations dlmfs_ops = { |
564 | .statfs = simple_statfs, | 564 | .statfs = simple_statfs, |
565 | .alloc_inode = dlmfs_alloc_inode, | 565 | .alloc_inode = dlmfs_alloc_inode, |
566 | .destroy_inode = dlmfs_destroy_inode, | 566 | .destroy_inode = dlmfs_destroy_inode, |
@@ -568,7 +568,7 @@ static struct super_operations dlmfs_ops = { | |||
568 | .drop_inode = generic_delete_inode, | 568 | .drop_inode = generic_delete_inode, |
569 | }; | 569 | }; |
570 | 570 | ||
571 | static struct inode_operations dlmfs_file_inode_operations = { | 571 | static const struct inode_operations dlmfs_file_inode_operations = { |
572 | .getattr = simple_getattr, | 572 | .getattr = simple_getattr, |
573 | }; | 573 | }; |
574 | 574 | ||
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 10953a508f2f..f2cd3bf9efb2 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -1365,13 +1365,13 @@ bail: | |||
1365 | return ret; | 1365 | return ret; |
1366 | } | 1366 | } |
1367 | 1367 | ||
1368 | struct inode_operations ocfs2_file_iops = { | 1368 | const struct inode_operations ocfs2_file_iops = { |
1369 | .setattr = ocfs2_setattr, | 1369 | .setattr = ocfs2_setattr, |
1370 | .getattr = ocfs2_getattr, | 1370 | .getattr = ocfs2_getattr, |
1371 | .permission = ocfs2_permission, | 1371 | .permission = ocfs2_permission, |
1372 | }; | 1372 | }; |
1373 | 1373 | ||
1374 | struct inode_operations ocfs2_special_file_iops = { | 1374 | const struct inode_operations ocfs2_special_file_iops = { |
1375 | .setattr = ocfs2_setattr, | 1375 | .setattr = ocfs2_setattr, |
1376 | .getattr = ocfs2_getattr, | 1376 | .getattr = ocfs2_getattr, |
1377 | .permission = ocfs2_permission, | 1377 | .permission = ocfs2_permission, |
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 601a453f18a8..cc973f01f6ce 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h | |||
@@ -28,8 +28,8 @@ | |||
28 | 28 | ||
29 | extern const struct file_operations ocfs2_fops; | 29 | extern const struct file_operations ocfs2_fops; |
30 | extern const struct file_operations ocfs2_dops; | 30 | extern const struct file_operations ocfs2_dops; |
31 | extern struct inode_operations ocfs2_file_iops; | 31 | extern const struct inode_operations ocfs2_file_iops; |
32 | extern struct inode_operations ocfs2_special_file_iops; | 32 | extern const struct inode_operations ocfs2_special_file_iops; |
33 | struct ocfs2_alloc_context; | 33 | struct ocfs2_alloc_context; |
34 | 34 | ||
35 | enum ocfs2_alloc_restarted { | 35 | enum ocfs2_alloc_restarted { |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index f3d7803b4b46..28dd757ff67d 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -1098,7 +1098,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1098 | BUG(); | 1098 | BUG(); |
1099 | } | 1099 | } |
1100 | 1100 | ||
1101 | /* Assume a directory heirarchy thusly: | 1101 | /* Assume a directory hierarchy thusly: |
1102 | * a/b/c | 1102 | * a/b/c |
1103 | * a/d | 1103 | * a/d |
1104 | * a,b,c, and d are all directories. | 1104 | * a,b,c, and d are all directories. |
@@ -2306,7 +2306,7 @@ leave: | |||
2306 | return status; | 2306 | return status; |
2307 | } | 2307 | } |
2308 | 2308 | ||
2309 | struct inode_operations ocfs2_dir_iops = { | 2309 | const struct inode_operations ocfs2_dir_iops = { |
2310 | .create = ocfs2_create, | 2310 | .create = ocfs2_create, |
2311 | .lookup = ocfs2_lookup, | 2311 | .lookup = ocfs2_lookup, |
2312 | .link = ocfs2_link, | 2312 | .link = ocfs2_link, |
diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h index 8425944fcccd..0975c7b7212b 100644 --- a/fs/ocfs2/namei.h +++ b/fs/ocfs2/namei.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #ifndef OCFS2_NAMEI_H | 26 | #ifndef OCFS2_NAMEI_H |
27 | #define OCFS2_NAMEI_H | 27 | #define OCFS2_NAMEI_H |
28 | 28 | ||
29 | extern struct inode_operations ocfs2_dir_iops; | 29 | extern const struct inode_operations ocfs2_dir_iops; |
30 | 30 | ||
31 | struct dentry *ocfs2_get_parent(struct dentry *child); | 31 | struct dentry *ocfs2_get_parent(struct dentry *child); |
32 | 32 | ||
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 6e300a88a47e..6534f92424dd 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -116,7 +116,7 @@ static void ocfs2_destroy_inode(struct inode *inode); | |||
116 | 116 | ||
117 | static unsigned long long ocfs2_max_file_offset(unsigned int blockshift); | 117 | static unsigned long long ocfs2_max_file_offset(unsigned int blockshift); |
118 | 118 | ||
119 | static struct super_operations ocfs2_sops = { | 119 | static const struct super_operations ocfs2_sops = { |
120 | .statfs = ocfs2_statfs, | 120 | .statfs = ocfs2_statfs, |
121 | .alloc_inode = ocfs2_alloc_inode, | 121 | .alloc_inode = ocfs2_alloc_inode, |
122 | .destroy_inode = ocfs2_destroy_inode, | 122 | .destroy_inode = ocfs2_destroy_inode, |
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 03b0191534d5..40dc1a51f4a9 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c | |||
@@ -170,12 +170,12 @@ bail: | |||
170 | return ERR_PTR(status); | 170 | return ERR_PTR(status); |
171 | } | 171 | } |
172 | 172 | ||
173 | struct inode_operations ocfs2_symlink_inode_operations = { | 173 | const struct inode_operations ocfs2_symlink_inode_operations = { |
174 | .readlink = page_readlink, | 174 | .readlink = page_readlink, |
175 | .follow_link = ocfs2_follow_link, | 175 | .follow_link = ocfs2_follow_link, |
176 | .getattr = ocfs2_getattr, | 176 | .getattr = ocfs2_getattr, |
177 | }; | 177 | }; |
178 | struct inode_operations ocfs2_fast_symlink_inode_operations = { | 178 | const struct inode_operations ocfs2_fast_symlink_inode_operations = { |
179 | .readlink = ocfs2_readlink, | 179 | .readlink = ocfs2_readlink, |
180 | .follow_link = ocfs2_follow_link, | 180 | .follow_link = ocfs2_follow_link, |
181 | .getattr = ocfs2_getattr, | 181 | .getattr = ocfs2_getattr, |
diff --git a/fs/ocfs2/symlink.h b/fs/ocfs2/symlink.h index 1ea9e4d9e9eb..65a6c9c6ad51 100644 --- a/fs/ocfs2/symlink.h +++ b/fs/ocfs2/symlink.h | |||
@@ -26,8 +26,8 @@ | |||
26 | #ifndef OCFS2_SYMLINK_H | 26 | #ifndef OCFS2_SYMLINK_H |
27 | #define OCFS2_SYMLINK_H | 27 | #define OCFS2_SYMLINK_H |
28 | 28 | ||
29 | extern struct inode_operations ocfs2_symlink_inode_operations; | 29 | extern const struct inode_operations ocfs2_symlink_inode_operations; |
30 | extern struct inode_operations ocfs2_fast_symlink_inode_operations; | 30 | extern const struct inode_operations ocfs2_fast_symlink_inode_operations; |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * Test whether an inode is a fast symlink. | 33 | * Test whether an inode is a fast symlink. |
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 99c0bc37ba09..bde1c164417d 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c | |||
@@ -169,7 +169,7 @@ static const struct file_operations openprom_operations = { | |||
169 | 169 | ||
170 | static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 170 | static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *); |
171 | 171 | ||
172 | static struct inode_operations openprom_inode_operations = { | 172 | static const struct inode_operations openprom_inode_operations = { |
173 | .lookup = openpromfs_lookup, | 173 | .lookup = openpromfs_lookup, |
174 | }; | 174 | }; |
175 | 175 | ||
@@ -364,7 +364,7 @@ static int openprom_remount(struct super_block *sb, int *flags, char *data) | |||
364 | return 0; | 364 | return 0; |
365 | } | 365 | } |
366 | 366 | ||
367 | static struct super_operations openprom_sops = { | 367 | static const struct super_operations openprom_sops = { |
368 | .alloc_inode = openprom_alloc_inode, | 368 | .alloc_inode = openprom_alloc_inode, |
369 | .destroy_inode = openprom_destroy_inode, | 369 | .destroy_inode = openprom_destroy_inode, |
370 | .read_inode = openprom_read_inode, | 370 | .read_inode = openprom_read_inode, |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 3d73d94d93a7..22d38ffc9ef0 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -358,14 +358,13 @@ void delete_partition(struct gendisk *disk, int part) | |||
358 | p->ios[0] = p->ios[1] = 0; | 358 | p->ios[0] = p->ios[1] = 0; |
359 | p->sectors[0] = p->sectors[1] = 0; | 359 | p->sectors[0] = p->sectors[1] = 0; |
360 | sysfs_remove_link(&p->kobj, "subsystem"); | 360 | sysfs_remove_link(&p->kobj, "subsystem"); |
361 | if (p->holder_dir) | 361 | kobject_unregister(p->holder_dir); |
362 | kobject_unregister(p->holder_dir); | ||
363 | kobject_uevent(&p->kobj, KOBJ_REMOVE); | 362 | kobject_uevent(&p->kobj, KOBJ_REMOVE); |
364 | kobject_del(&p->kobj); | 363 | kobject_del(&p->kobj); |
365 | kobject_put(&p->kobj); | 364 | kobject_put(&p->kobj); |
366 | } | 365 | } |
367 | 366 | ||
368 | void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) | 367 | void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) |
369 | { | 368 | { |
370 | struct hd_struct *p; | 369 | struct hd_struct *p; |
371 | 370 | ||
@@ -390,6 +389,15 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) | |||
390 | if (!disk->part_uevent_suppress) | 389 | if (!disk->part_uevent_suppress) |
391 | kobject_uevent(&p->kobj, KOBJ_ADD); | 390 | kobject_uevent(&p->kobj, KOBJ_ADD); |
392 | sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem"); | 391 | sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem"); |
392 | if (flags & ADDPART_FLAG_WHOLEDISK) { | ||
393 | static struct attribute addpartattr = { | ||
394 | .name = "whole_disk", | ||
395 | .mode = S_IRUSR | S_IRGRP | S_IROTH, | ||
396 | .owner = THIS_MODULE, | ||
397 | }; | ||
398 | |||
399 | sysfs_create_file(&p->kobj, &addpartattr); | ||
400 | } | ||
393 | partition_sysfs_add_subdir(p); | 401 | partition_sysfs_add_subdir(p); |
394 | disk->part[part-1] = p; | 402 | disk->part[part-1] = p; |
395 | } | 403 | } |
@@ -543,9 +551,9 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
543 | printk(" %s: p%d exceeds device capacity\n", | 551 | printk(" %s: p%d exceeds device capacity\n", |
544 | disk->disk_name, p); | 552 | disk->disk_name, p); |
545 | } | 553 | } |
546 | add_partition(disk, p, from, size); | 554 | add_partition(disk, p, from, size, state->parts[p].flags); |
547 | #ifdef CONFIG_BLK_DEV_MD | 555 | #ifdef CONFIG_BLK_DEV_MD |
548 | if (state->parts[p].flags) | 556 | if (state->parts[p].flags & ADDPART_FLAG_RAID) |
549 | md_autodetect_dev(bdev->bd_dev+p); | 557 | md_autodetect_dev(bdev->bd_dev+p); |
550 | #endif | 558 | #endif |
551 | } | 559 | } |
@@ -594,10 +602,8 @@ void del_gendisk(struct gendisk *disk) | |||
594 | disk->stamp = 0; | 602 | disk->stamp = 0; |
595 | 603 | ||
596 | kobject_uevent(&disk->kobj, KOBJ_REMOVE); | 604 | kobject_uevent(&disk->kobj, KOBJ_REMOVE); |
597 | if (disk->holder_dir) | 605 | kobject_unregister(disk->holder_dir); |
598 | kobject_unregister(disk->holder_dir); | 606 | kobject_unregister(disk->slave_dir); |
599 | if (disk->slave_dir) | ||
600 | kobject_unregister(disk->slave_dir); | ||
601 | if (disk->driverfs_dev) { | 607 | if (disk->driverfs_dev) { |
602 | char *disk_name = make_block_name(disk); | 608 | char *disk_name = make_block_name(disk); |
603 | sysfs_remove_link(&disk->kobj, "device"); | 609 | sysfs_remove_link(&disk->kobj, "device"); |
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 8c7af1777819..4ccec4cd1367 100644 --- a/fs/partitions/msdos.c +++ b/fs/partitions/msdos.c | |||
@@ -63,15 +63,25 @@ msdos_magic_present(unsigned char *p) | |||
63 | #define AIX_LABEL_MAGIC4 0xC1 | 63 | #define AIX_LABEL_MAGIC4 0xC1 |
64 | static int aix_magic_present(unsigned char *p, struct block_device *bdev) | 64 | static int aix_magic_present(unsigned char *p, struct block_device *bdev) |
65 | { | 65 | { |
66 | struct partition *pt = (struct partition *) (p + 0x1be); | ||
66 | Sector sect; | 67 | Sector sect; |
67 | unsigned char *d; | 68 | unsigned char *d; |
68 | int ret = 0; | 69 | int slot, ret = 0; |
69 | 70 | ||
70 | if (p[0] != AIX_LABEL_MAGIC1 && | 71 | if (!(p[0] == AIX_LABEL_MAGIC1 && |
71 | p[1] != AIX_LABEL_MAGIC2 && | 72 | p[1] == AIX_LABEL_MAGIC2 && |
72 | p[2] != AIX_LABEL_MAGIC3 && | 73 | p[2] == AIX_LABEL_MAGIC3 && |
73 | p[3] != AIX_LABEL_MAGIC4) | 74 | p[3] == AIX_LABEL_MAGIC4)) |
74 | return 0; | 75 | return 0; |
76 | /* Assume the partition table is valid if Linux partitions exists */ | ||
77 | for (slot = 1; slot <= 4; slot++, pt++) { | ||
78 | if (pt->sys_ind == LINUX_SWAP_PARTITION || | ||
79 | pt->sys_ind == LINUX_RAID_PARTITION || | ||
80 | pt->sys_ind == LINUX_DATA_PARTITION || | ||
81 | pt->sys_ind == LINUX_LVM_PARTITION || | ||
82 | is_extended_partition(pt)) | ||
83 | return 0; | ||
84 | } | ||
75 | d = read_dev_sector(bdev, 7, §); | 85 | d = read_dev_sector(bdev, 7, §); |
76 | if (d) { | 86 | if (d) { |
77 | if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M') | 87 | if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M') |
@@ -155,7 +165,7 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev, | |||
155 | 165 | ||
156 | put_partition(state, state->next, next, size); | 166 | put_partition(state, state->next, next, size); |
157 | if (SYS_IND(p) == LINUX_RAID_PARTITION) | 167 | if (SYS_IND(p) == LINUX_RAID_PARTITION) |
158 | state->parts[state->next].flags = 1; | 168 | state->parts[state->next].flags = ADDPART_FLAG_RAID; |
159 | loopct = 0; | 169 | loopct = 0; |
160 | if (++state->next == state->limit) | 170 | if (++state->next == state->limit) |
161 | goto done; | 171 | goto done; |
diff --git a/fs/partitions/sgi.c b/fs/partitions/sgi.c index 6fa4ff895104..ed5ac83fe83a 100644 --- a/fs/partitions/sgi.c +++ b/fs/partitions/sgi.c | |||
@@ -72,7 +72,7 @@ int sgi_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
72 | if (blocks) { | 72 | if (blocks) { |
73 | put_partition(state, slot, start, blocks); | 73 | put_partition(state, slot, start, blocks); |
74 | if (be32_to_cpu(p->type) == LINUX_RAID_PARTITION) | 74 | if (be32_to_cpu(p->type) == LINUX_RAID_PARTITION) |
75 | state->parts[slot].flags = 1; | 75 | state->parts[slot].flags = ADDPART_FLAG_RAID; |
76 | } | 76 | } |
77 | slot++; | 77 | slot++; |
78 | } | 78 | } |
diff --git a/fs/partitions/sun.c b/fs/partitions/sun.c index 0a5927c806ca..123f8b46c8ba 100644 --- a/fs/partitions/sun.c +++ b/fs/partitions/sun.c | |||
@@ -80,8 +80,11 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
80 | num_sectors = be32_to_cpu(p->num_sectors); | 80 | num_sectors = be32_to_cpu(p->num_sectors); |
81 | if (num_sectors) { | 81 | if (num_sectors) { |
82 | put_partition(state, slot, st_sector, num_sectors); | 82 | put_partition(state, slot, st_sector, num_sectors); |
83 | state->parts[slot].flags = 0; | ||
83 | if (label->infos[i].id == LINUX_RAID_PARTITION) | 84 | if (label->infos[i].id == LINUX_RAID_PARTITION) |
84 | state->parts[slot].flags = 1; | 85 | state->parts[slot].flags |= ADDPART_FLAG_RAID; |
86 | if (label->infos[i].id == SUN_WHOLE_DISK) | ||
87 | state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK; | ||
85 | } | 88 | } |
86 | slot++; | 89 | slot++; |
87 | } | 90 | } |
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/uio.h> | 16 | #include <linux/uio.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
19 | #include <linux/audit.h> | ||
19 | 20 | ||
20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
21 | #include <asm/ioctls.h> | 22 | #include <asm/ioctls.h> |
@@ -985,6 +986,10 @@ int do_pipe(int *fd) | |||
985 | goto err_fdr; | 986 | goto err_fdr; |
986 | fdw = error; | 987 | fdw = error; |
987 | 988 | ||
989 | error = audit_fd_pair(fdr, fdw); | ||
990 | if (error < 0) | ||
991 | goto err_fdw; | ||
992 | |||
988 | fd_install(fdr, fr); | 993 | fd_install(fdr, fr); |
989 | fd_install(fdw, fw); | 994 | fd_install(fdw, fw); |
990 | fd[0] = fdr; | 995 | fd[0] = fdr; |
@@ -992,6 +997,8 @@ int do_pipe(int *fd) | |||
992 | 997 | ||
993 | return 0; | 998 | return 0; |
994 | 999 | ||
1000 | err_fdw: | ||
1001 | put_unused_fd(fdw); | ||
995 | err_fdr: | 1002 | err_fdr: |
996 | put_unused_fd(fdr); | 1003 | put_unused_fd(fdr); |
997 | err_read_pipe: | 1004 | err_read_pipe: |
diff --git a/fs/proc/Makefile b/fs/proc/Makefile index f6c776272572..a6b3a8f878f0 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile | |||
@@ -8,7 +8,7 @@ proc-y := nommu.o task_nommu.o | |||
8 | proc-$(CONFIG_MMU) := mmu.o task_mmu.o | 8 | proc-$(CONFIG_MMU) := mmu.o task_mmu.o |
9 | 9 | ||
10 | proc-y += inode.o root.o base.o generic.o array.o \ | 10 | proc-y += inode.o root.o base.o generic.o array.o \ |
11 | proc_tty.o proc_misc.o | 11 | proc_tty.o proc_misc.o proc_sysctl.o |
12 | 12 | ||
13 | proc-$(CONFIG_PROC_KCORE) += kcore.o | 13 | proc-$(CONFIG_PROC_KCORE) += kcore.o |
14 | proc-$(CONFIG_PROC_VMCORE) += vmcore.o | 14 | proc-$(CONFIG_PROC_VMCORE) += vmcore.o |
diff --git a/fs/proc/array.c b/fs/proc/array.c index 70e4fab117b1..07c9cdbcdcac 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -351,7 +351,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
351 | struct signal_struct *sig = task->signal; | 351 | struct signal_struct *sig = task->signal; |
352 | 352 | ||
353 | if (sig->tty) { | 353 | if (sig->tty) { |
354 | tty_pgrp = sig->tty->pgrp; | 354 | tty_pgrp = pid_nr(sig->tty->pgrp); |
355 | tty_nr = new_encode_dev(tty_devnum(sig->tty)); | 355 | tty_nr = new_encode_dev(tty_devnum(sig->tty)); |
356 | } | 356 | } |
357 | 357 | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index 1a979ea3b379..01f7769da8e6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -93,8 +93,8 @@ struct pid_entry { | |||
93 | int len; | 93 | int len; |
94 | char *name; | 94 | char *name; |
95 | mode_t mode; | 95 | mode_t mode; |
96 | struct inode_operations *iop; | 96 | const struct inode_operations *iop; |
97 | struct file_operations *fop; | 97 | const struct file_operations *fop; |
98 | union proc_op op; | 98 | union proc_op op; |
99 | }; | 99 | }; |
100 | 100 | ||
@@ -352,7 +352,7 @@ static int proc_setattr(struct dentry *dentry, struct iattr *attr) | |||
352 | return error; | 352 | return error; |
353 | } | 353 | } |
354 | 354 | ||
355 | static struct inode_operations proc_def_inode_operations = { | 355 | static const struct inode_operations proc_def_inode_operations = { |
356 | .setattr = proc_setattr, | 356 | .setattr = proc_setattr, |
357 | }; | 357 | }; |
358 | 358 | ||
@@ -424,7 +424,7 @@ static unsigned mounts_poll(struct file *file, poll_table *wait) | |||
424 | return res; | 424 | return res; |
425 | } | 425 | } |
426 | 426 | ||
427 | static struct file_operations proc_mounts_operations = { | 427 | static const struct file_operations proc_mounts_operations = { |
428 | .open = mounts_open, | 428 | .open = mounts_open, |
429 | .read = seq_read, | 429 | .read = seq_read, |
430 | .llseek = seq_lseek, | 430 | .llseek = seq_lseek, |
@@ -462,7 +462,7 @@ static int mountstats_open(struct inode *inode, struct file *file) | |||
462 | return ret; | 462 | return ret; |
463 | } | 463 | } |
464 | 464 | ||
465 | static struct file_operations proc_mountstats_operations = { | 465 | static const struct file_operations proc_mountstats_operations = { |
466 | .open = mountstats_open, | 466 | .open = mountstats_open, |
467 | .read = seq_read, | 467 | .read = seq_read, |
468 | .llseek = seq_lseek, | 468 | .llseek = seq_lseek, |
@@ -501,7 +501,7 @@ out_no_task: | |||
501 | return length; | 501 | return length; |
502 | } | 502 | } |
503 | 503 | ||
504 | static struct file_operations proc_info_file_operations = { | 504 | static const struct file_operations proc_info_file_operations = { |
505 | .read = proc_info_read, | 505 | .read = proc_info_read, |
506 | }; | 506 | }; |
507 | 507 | ||
@@ -581,7 +581,7 @@ out_no_task: | |||
581 | 581 | ||
582 | #ifndef mem_write | 582 | #ifndef mem_write |
583 | /* This is a security hazard */ | 583 | /* This is a security hazard */ |
584 | static ssize_t mem_write(struct file * file, const char * buf, | 584 | static ssize_t mem_write(struct file * file, const char __user *buf, |
585 | size_t count, loff_t *ppos) | 585 | size_t count, loff_t *ppos) |
586 | { | 586 | { |
587 | int copied; | 587 | int copied; |
@@ -646,7 +646,7 @@ static loff_t mem_lseek(struct file * file, loff_t offset, int orig) | |||
646 | return file->f_pos; | 646 | return file->f_pos; |
647 | } | 647 | } |
648 | 648 | ||
649 | static struct file_operations proc_mem_operations = { | 649 | static const struct file_operations proc_mem_operations = { |
650 | .llseek = mem_lseek, | 650 | .llseek = mem_lseek, |
651 | .read = mem_read, | 651 | .read = mem_read, |
652 | .write = mem_write, | 652 | .write = mem_write, |
@@ -710,7 +710,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
710 | return end - buffer; | 710 | return end - buffer; |
711 | } | 711 | } |
712 | 712 | ||
713 | static struct file_operations proc_oom_adjust_operations = { | 713 | static const struct file_operations proc_oom_adjust_operations = { |
714 | .read = oom_adjust_read, | 714 | .read = oom_adjust_read, |
715 | .write = oom_adjust_write, | 715 | .write = oom_adjust_write, |
716 | }; | 716 | }; |
@@ -777,7 +777,7 @@ out_free_page: | |||
777 | return length; | 777 | return length; |
778 | } | 778 | } |
779 | 779 | ||
780 | static struct file_operations proc_loginuid_operations = { | 780 | static const struct file_operations proc_loginuid_operations = { |
781 | .read = proc_loginuid_read, | 781 | .read = proc_loginuid_read, |
782 | .write = proc_loginuid_write, | 782 | .write = proc_loginuid_write, |
783 | }; | 783 | }; |
@@ -849,7 +849,7 @@ out_no_task: | |||
849 | return result; | 849 | return result; |
850 | } | 850 | } |
851 | 851 | ||
852 | static struct file_operations proc_seccomp_operations = { | 852 | static const struct file_operations proc_seccomp_operations = { |
853 | .read = seccomp_read, | 853 | .read = seccomp_read, |
854 | .write = seccomp_write, | 854 | .write = seccomp_write, |
855 | }; | 855 | }; |
@@ -908,7 +908,7 @@ static ssize_t proc_fault_inject_write(struct file * file, | |||
908 | return end - buffer; | 908 | return end - buffer; |
909 | } | 909 | } |
910 | 910 | ||
911 | static struct file_operations proc_fault_inject_operations = { | 911 | static const struct file_operations proc_fault_inject_operations = { |
912 | .read = proc_fault_inject_read, | 912 | .read = proc_fault_inject_read, |
913 | .write = proc_fault_inject_write, | 913 | .write = proc_fault_inject_write, |
914 | }; | 914 | }; |
@@ -980,7 +980,7 @@ out: | |||
980 | return error; | 980 | return error; |
981 | } | 981 | } |
982 | 982 | ||
983 | static struct inode_operations proc_pid_link_inode_operations = { | 983 | static const struct inode_operations proc_pid_link_inode_operations = { |
984 | .readlink = proc_pid_readlink, | 984 | .readlink = proc_pid_readlink, |
985 | .follow_link = proc_pid_follow_link, | 985 | .follow_link = proc_pid_follow_link, |
986 | .setattr = proc_setattr, | 986 | .setattr = proc_setattr, |
@@ -1408,7 +1408,7 @@ out_no_task: | |||
1408 | return retval; | 1408 | return retval; |
1409 | } | 1409 | } |
1410 | 1410 | ||
1411 | static struct file_operations proc_fd_operations = { | 1411 | static const struct file_operations proc_fd_operations = { |
1412 | .read = generic_read_dir, | 1412 | .read = generic_read_dir, |
1413 | .readdir = proc_readfd, | 1413 | .readdir = proc_readfd, |
1414 | }; | 1414 | }; |
@@ -1416,7 +1416,7 @@ static struct file_operations proc_fd_operations = { | |||
1416 | /* | 1416 | /* |
1417 | * proc directories can do almost nothing.. | 1417 | * proc directories can do almost nothing.. |
1418 | */ | 1418 | */ |
1419 | static struct inode_operations proc_fd_inode_operations = { | 1419 | static const struct inode_operations proc_fd_inode_operations = { |
1420 | .lookup = proc_lookupfd, | 1420 | .lookup = proc_lookupfd, |
1421 | .setattr = proc_setattr, | 1421 | .setattr = proc_setattr, |
1422 | }; | 1422 | }; |
@@ -1623,7 +1623,7 @@ out_no_task: | |||
1623 | return length; | 1623 | return length; |
1624 | } | 1624 | } |
1625 | 1625 | ||
1626 | static struct file_operations proc_pid_attr_operations = { | 1626 | static const struct file_operations proc_pid_attr_operations = { |
1627 | .read = proc_pid_attr_read, | 1627 | .read = proc_pid_attr_read, |
1628 | .write = proc_pid_attr_write, | 1628 | .write = proc_pid_attr_write, |
1629 | }; | 1629 | }; |
@@ -1644,7 +1644,7 @@ static int proc_attr_dir_readdir(struct file * filp, | |||
1644 | attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff)); | 1644 | attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff)); |
1645 | } | 1645 | } |
1646 | 1646 | ||
1647 | static struct file_operations proc_attr_dir_operations = { | 1647 | static const struct file_operations proc_attr_dir_operations = { |
1648 | .read = generic_read_dir, | 1648 | .read = generic_read_dir, |
1649 | .readdir = proc_attr_dir_readdir, | 1649 | .readdir = proc_attr_dir_readdir, |
1650 | }; | 1650 | }; |
@@ -1656,7 +1656,7 @@ static struct dentry *proc_attr_dir_lookup(struct inode *dir, | |||
1656 | attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); | 1656 | attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); |
1657 | } | 1657 | } |
1658 | 1658 | ||
1659 | static struct inode_operations proc_attr_dir_inode_operations = { | 1659 | static const struct inode_operations proc_attr_dir_inode_operations = { |
1660 | .lookup = proc_attr_dir_lookup, | 1660 | .lookup = proc_attr_dir_lookup, |
1661 | .getattr = pid_getattr, | 1661 | .getattr = pid_getattr, |
1662 | .setattr = proc_setattr, | 1662 | .setattr = proc_setattr, |
@@ -1682,7 +1682,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
1682 | return ERR_PTR(vfs_follow_link(nd,tmp)); | 1682 | return ERR_PTR(vfs_follow_link(nd,tmp)); |
1683 | } | 1683 | } |
1684 | 1684 | ||
1685 | static struct inode_operations proc_self_inode_operations = { | 1685 | static const struct inode_operations proc_self_inode_operations = { |
1686 | .readlink = proc_self_readlink, | 1686 | .readlink = proc_self_readlink, |
1687 | .follow_link = proc_self_follow_link, | 1687 | .follow_link = proc_self_follow_link, |
1688 | }; | 1688 | }; |
@@ -1810,17 +1810,21 @@ static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filld | |||
1810 | static int proc_pid_io_accounting(struct task_struct *task, char *buffer) | 1810 | static int proc_pid_io_accounting(struct task_struct *task, char *buffer) |
1811 | { | 1811 | { |
1812 | return sprintf(buffer, | 1812 | return sprintf(buffer, |
1813 | #ifdef CONFIG_TASK_XACCT | ||
1813 | "rchar: %llu\n" | 1814 | "rchar: %llu\n" |
1814 | "wchar: %llu\n" | 1815 | "wchar: %llu\n" |
1815 | "syscr: %llu\n" | 1816 | "syscr: %llu\n" |
1816 | "syscw: %llu\n" | 1817 | "syscw: %llu\n" |
1818 | #endif | ||
1817 | "read_bytes: %llu\n" | 1819 | "read_bytes: %llu\n" |
1818 | "write_bytes: %llu\n" | 1820 | "write_bytes: %llu\n" |
1819 | "cancelled_write_bytes: %llu\n", | 1821 | "cancelled_write_bytes: %llu\n", |
1822 | #ifdef CONFIG_TASK_XACCT | ||
1820 | (unsigned long long)task->rchar, | 1823 | (unsigned long long)task->rchar, |
1821 | (unsigned long long)task->wchar, | 1824 | (unsigned long long)task->wchar, |
1822 | (unsigned long long)task->syscr, | 1825 | (unsigned long long)task->syscr, |
1823 | (unsigned long long)task->syscw, | 1826 | (unsigned long long)task->syscw, |
1827 | #endif | ||
1824 | (unsigned long long)task->ioac.read_bytes, | 1828 | (unsigned long long)task->ioac.read_bytes, |
1825 | (unsigned long long)task->ioac.write_bytes, | 1829 | (unsigned long long)task->ioac.write_bytes, |
1826 | (unsigned long long)task->ioac.cancelled_write_bytes); | 1830 | (unsigned long long)task->ioac.cancelled_write_bytes); |
@@ -1830,8 +1834,8 @@ static int proc_pid_io_accounting(struct task_struct *task, char *buffer) | |||
1830 | /* | 1834 | /* |
1831 | * Thread groups | 1835 | * Thread groups |
1832 | */ | 1836 | */ |
1833 | static struct file_operations proc_task_operations; | 1837 | static const struct file_operations proc_task_operations; |
1834 | static struct inode_operations proc_task_inode_operations; | 1838 | static const struct inode_operations proc_task_inode_operations; |
1835 | 1839 | ||
1836 | static struct pid_entry tgid_base_stuff[] = { | 1840 | static struct pid_entry tgid_base_stuff[] = { |
1837 | DIR("task", S_IRUGO|S_IXUGO, task), | 1841 | DIR("task", S_IRUGO|S_IXUGO, task), |
@@ -1890,7 +1894,7 @@ static int proc_tgid_base_readdir(struct file * filp, | |||
1890 | tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff)); | 1894 | tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff)); |
1891 | } | 1895 | } |
1892 | 1896 | ||
1893 | static struct file_operations proc_tgid_base_operations = { | 1897 | static const struct file_operations proc_tgid_base_operations = { |
1894 | .read = generic_read_dir, | 1898 | .read = generic_read_dir, |
1895 | .readdir = proc_tgid_base_readdir, | 1899 | .readdir = proc_tgid_base_readdir, |
1896 | }; | 1900 | }; |
@@ -1900,7 +1904,7 @@ static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *de | |||
1900 | tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); | 1904 | tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); |
1901 | } | 1905 | } |
1902 | 1906 | ||
1903 | static struct inode_operations proc_tgid_base_inode_operations = { | 1907 | static const struct inode_operations proc_tgid_base_inode_operations = { |
1904 | .lookup = proc_tgid_base_lookup, | 1908 | .lookup = proc_tgid_base_lookup, |
1905 | .getattr = pid_getattr, | 1909 | .getattr = pid_getattr, |
1906 | .setattr = proc_setattr, | 1910 | .setattr = proc_setattr, |
@@ -2173,12 +2177,12 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den | |||
2173 | tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); | 2177 | tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); |
2174 | } | 2178 | } |
2175 | 2179 | ||
2176 | static struct file_operations proc_tid_base_operations = { | 2180 | static const struct file_operations proc_tid_base_operations = { |
2177 | .read = generic_read_dir, | 2181 | .read = generic_read_dir, |
2178 | .readdir = proc_tid_base_readdir, | 2182 | .readdir = proc_tid_base_readdir, |
2179 | }; | 2183 | }; |
2180 | 2184 | ||
2181 | static struct inode_operations proc_tid_base_inode_operations = { | 2185 | static const struct inode_operations proc_tid_base_inode_operations = { |
2182 | .lookup = proc_tid_base_lookup, | 2186 | .lookup = proc_tid_base_lookup, |
2183 | .getattr = pid_getattr, | 2187 | .getattr = pid_getattr, |
2184 | .setattr = proc_setattr, | 2188 | .setattr = proc_setattr, |
@@ -2404,13 +2408,13 @@ static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct | |||
2404 | return 0; | 2408 | return 0; |
2405 | } | 2409 | } |
2406 | 2410 | ||
2407 | static struct inode_operations proc_task_inode_operations = { | 2411 | static const struct inode_operations proc_task_inode_operations = { |
2408 | .lookup = proc_task_lookup, | 2412 | .lookup = proc_task_lookup, |
2409 | .getattr = proc_task_getattr, | 2413 | .getattr = proc_task_getattr, |
2410 | .setattr = proc_setattr, | 2414 | .setattr = proc_setattr, |
2411 | }; | 2415 | }; |
2412 | 2416 | ||
2413 | static struct file_operations proc_task_operations = { | 2417 | static const struct file_operations proc_task_operations = { |
2414 | .read = generic_read_dir, | 2418 | .read = generic_read_dir, |
2415 | .readdir = proc_task_readdir, | 2419 | .readdir = proc_task_readdir, |
2416 | }; | 2420 | }; |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 853cb877d5f3..775fb21294d8 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -32,14 +32,14 @@ static loff_t proc_file_lseek(struct file *, loff_t, int); | |||
32 | 32 | ||
33 | DEFINE_SPINLOCK(proc_subdir_lock); | 33 | DEFINE_SPINLOCK(proc_subdir_lock); |
34 | 34 | ||
35 | int proc_match(int len, const char *name, struct proc_dir_entry *de) | 35 | static int proc_match(int len, const char *name, struct proc_dir_entry *de) |
36 | { | 36 | { |
37 | if (de->namelen != len) | 37 | if (de->namelen != len) |
38 | return 0; | 38 | return 0; |
39 | return !memcmp(name, de->name, len); | 39 | return !memcmp(name, de->name, len); |
40 | } | 40 | } |
41 | 41 | ||
42 | static struct file_operations proc_file_operations = { | 42 | static const struct file_operations proc_file_operations = { |
43 | .llseek = proc_file_lseek, | 43 | .llseek = proc_file_lseek, |
44 | .read = proc_file_read, | 44 | .read = proc_file_read, |
45 | .write = proc_file_write, | 45 | .write = proc_file_write, |
@@ -265,7 +265,7 @@ static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
268 | static struct inode_operations proc_file_inode_operations = { | 268 | static const struct inode_operations proc_file_inode_operations = { |
269 | .setattr = proc_notify_change, | 269 | .setattr = proc_notify_change, |
270 | }; | 270 | }; |
271 | 271 | ||
@@ -357,7 +357,7 @@ static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
357 | return NULL; | 357 | return NULL; |
358 | } | 358 | } |
359 | 359 | ||
360 | static struct inode_operations proc_link_inode_operations = { | 360 | static const struct inode_operations proc_link_inode_operations = { |
361 | .readlink = generic_readlink, | 361 | .readlink = generic_readlink, |
362 | .follow_link = proc_follow_link, | 362 | .follow_link = proc_follow_link, |
363 | }; | 363 | }; |
@@ -497,7 +497,7 @@ out: unlock_kernel(); | |||
497 | * use the in-memory "struct proc_dir_entry" tree to parse | 497 | * use the in-memory "struct proc_dir_entry" tree to parse |
498 | * the /proc directory. | 498 | * the /proc directory. |
499 | */ | 499 | */ |
500 | static struct file_operations proc_dir_operations = { | 500 | static const struct file_operations proc_dir_operations = { |
501 | .read = generic_read_dir, | 501 | .read = generic_read_dir, |
502 | .readdir = proc_readdir, | 502 | .readdir = proc_readdir, |
503 | }; | 503 | }; |
@@ -505,7 +505,7 @@ static struct file_operations proc_dir_operations = { | |||
505 | /* | 505 | /* |
506 | * proc directories can do almost nothing.. | 506 | * proc directories can do almost nothing.. |
507 | */ | 507 | */ |
508 | static struct inode_operations proc_dir_inode_operations = { | 508 | static const struct inode_operations proc_dir_inode_operations = { |
509 | .lookup = proc_lookup, | 509 | .lookup = proc_lookup, |
510 | .getattr = proc_getattr, | 510 | .getattr = proc_getattr, |
511 | .setattr = proc_notify_change, | 511 | .setattr = proc_notify_change, |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index e26945ba685b..c372eb151a3a 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -132,7 +132,7 @@ static int proc_remount(struct super_block *sb, int *flags, char *data) | |||
132 | return 0; | 132 | return 0; |
133 | } | 133 | } |
134 | 134 | ||
135 | static struct super_operations proc_sops = { | 135 | static const struct super_operations proc_sops = { |
136 | .alloc_inode = proc_alloc_inode, | 136 | .alloc_inode = proc_alloc_inode, |
137 | .destroy_inode = proc_destroy_inode, | 137 | .destroy_inode = proc_destroy_inode, |
138 | .read_inode = proc_read_inode, | 138 | .read_inode = proc_read_inode, |
@@ -161,6 +161,7 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, | |||
161 | if (!inode) | 161 | if (!inode) |
162 | goto out_ino; | 162 | goto out_ino; |
163 | 163 | ||
164 | PROC_I(inode)->fd = 0; | ||
164 | PROC_I(inode)->pde = de; | 165 | PROC_I(inode)->pde = de; |
165 | if (de) { | 166 | if (de) { |
166 | if (de->mode) { | 167 | if (de->mode) { |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 987c773dbb20..c932aa65e198 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -11,6 +11,8 @@ | |||
11 | 11 | ||
12 | #include <linux/proc_fs.h> | 12 | #include <linux/proc_fs.h> |
13 | 13 | ||
14 | extern int proc_sys_init(void); | ||
15 | |||
14 | struct vmalloc_info { | 16 | struct vmalloc_info { |
15 | unsigned long used; | 17 | unsigned long used; |
16 | unsigned long largest_chunk; | 18 | unsigned long largest_chunk; |
@@ -38,13 +40,13 @@ extern int proc_tgid_stat(struct task_struct *, char *); | |||
38 | extern int proc_pid_status(struct task_struct *, char *); | 40 | extern int proc_pid_status(struct task_struct *, char *); |
39 | extern int proc_pid_statm(struct task_struct *, char *); | 41 | extern int proc_pid_statm(struct task_struct *, char *); |
40 | 42 | ||
41 | extern struct file_operations proc_maps_operations; | 43 | extern const struct file_operations proc_maps_operations; |
42 | extern struct file_operations proc_numa_maps_operations; | 44 | extern const struct file_operations proc_numa_maps_operations; |
43 | extern struct file_operations proc_smaps_operations; | 45 | extern const struct file_operations proc_smaps_operations; |
44 | 46 | ||
45 | extern struct file_operations proc_maps_operations; | 47 | extern const struct file_operations proc_maps_operations; |
46 | extern struct file_operations proc_numa_maps_operations; | 48 | extern const struct file_operations proc_numa_maps_operations; |
47 | extern struct file_operations proc_smaps_operations; | 49 | extern const struct file_operations proc_smaps_operations; |
48 | 50 | ||
49 | 51 | ||
50 | void free_proc_entry(struct proc_dir_entry *de); | 52 | void free_proc_entry(struct proc_dir_entry *de); |
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index 5ec67257e5f9..22f789de3909 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c | |||
@@ -128,7 +128,7 @@ static int proc_nommu_vma_list_open(struct inode *inode, struct file *file) | |||
128 | return seq_open(file, &proc_nommu_vma_list_seqop); | 128 | return seq_open(file, &proc_nommu_vma_list_seqop); |
129 | } | 129 | } |
130 | 130 | ||
131 | static struct file_operations proc_nommu_vma_list_operations = { | 131 | static const struct file_operations proc_nommu_vma_list_operations = { |
132 | .open = proc_nommu_vma_list_open, | 132 | .open = proc_nommu_vma_list_open, |
133 | .read = seq_read, | 133 | .read = seq_read, |
134 | .llseek = seq_lseek, | 134 | .llseek = seq_lseek, |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index b37ce33f67ea..e2c4c0a5c90d 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -121,16 +121,11 @@ static int meminfo_read_proc(char *page, char **start, off_t off, | |||
121 | { | 121 | { |
122 | struct sysinfo i; | 122 | struct sysinfo i; |
123 | int len; | 123 | int len; |
124 | unsigned long inactive; | ||
125 | unsigned long active; | ||
126 | unsigned long free; | ||
127 | unsigned long committed; | 124 | unsigned long committed; |
128 | unsigned long allowed; | 125 | unsigned long allowed; |
129 | struct vmalloc_info vmi; | 126 | struct vmalloc_info vmi; |
130 | long cached; | 127 | long cached; |
131 | 128 | ||
132 | get_zone_counts(&active, &inactive, &free); | ||
133 | |||
134 | /* | 129 | /* |
135 | * display in kilobytes. | 130 | * display in kilobytes. |
136 | */ | 131 | */ |
@@ -187,8 +182,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off, | |||
187 | K(i.bufferram), | 182 | K(i.bufferram), |
188 | K(cached), | 183 | K(cached), |
189 | K(total_swapcache_pages), | 184 | K(total_swapcache_pages), |
190 | K(active), | 185 | K(global_page_state(NR_ACTIVE)), |
191 | K(inactive), | 186 | K(global_page_state(NR_INACTIVE)), |
192 | #ifdef CONFIG_HIGHMEM | 187 | #ifdef CONFIG_HIGHMEM |
193 | K(i.totalhigh), | 188 | K(i.totalhigh), |
194 | K(i.freehigh), | 189 | K(i.freehigh), |
@@ -228,7 +223,7 @@ static int fragmentation_open(struct inode *inode, struct file *file) | |||
228 | return seq_open(file, &fragmentation_op); | 223 | return seq_open(file, &fragmentation_op); |
229 | } | 224 | } |
230 | 225 | ||
231 | static struct file_operations fragmentation_file_operations = { | 226 | static const struct file_operations fragmentation_file_operations = { |
232 | .open = fragmentation_open, | 227 | .open = fragmentation_open, |
233 | .read = seq_read, | 228 | .read = seq_read, |
234 | .llseek = seq_lseek, | 229 | .llseek = seq_lseek, |
@@ -241,7 +236,7 @@ static int zoneinfo_open(struct inode *inode, struct file *file) | |||
241 | return seq_open(file, &zoneinfo_op); | 236 | return seq_open(file, &zoneinfo_op); |
242 | } | 237 | } |
243 | 238 | ||
244 | static struct file_operations proc_zoneinfo_file_operations = { | 239 | static const struct file_operations proc_zoneinfo_file_operations = { |
245 | .open = zoneinfo_open, | 240 | .open = zoneinfo_open, |
246 | .read = seq_read, | 241 | .read = seq_read, |
247 | .llseek = seq_lseek, | 242 | .llseek = seq_lseek, |
@@ -266,7 +261,7 @@ static int cpuinfo_open(struct inode *inode, struct file *file) | |||
266 | return seq_open(file, &cpuinfo_op); | 261 | return seq_open(file, &cpuinfo_op); |
267 | } | 262 | } |
268 | 263 | ||
269 | static struct file_operations proc_cpuinfo_operations = { | 264 | static const struct file_operations proc_cpuinfo_operations = { |
270 | .open = cpuinfo_open, | 265 | .open = cpuinfo_open, |
271 | .read = seq_read, | 266 | .read = seq_read, |
272 | .llseek = seq_lseek, | 267 | .llseek = seq_lseek, |
@@ -325,7 +320,7 @@ static int devinfo_open(struct inode *inode, struct file *filp) | |||
325 | return seq_open(filp, &devinfo_ops); | 320 | return seq_open(filp, &devinfo_ops); |
326 | } | 321 | } |
327 | 322 | ||
328 | static struct file_operations proc_devinfo_operations = { | 323 | static const struct file_operations proc_devinfo_operations = { |
329 | .open = devinfo_open, | 324 | .open = devinfo_open, |
330 | .read = seq_read, | 325 | .read = seq_read, |
331 | .llseek = seq_lseek, | 326 | .llseek = seq_lseek, |
@@ -337,7 +332,7 @@ static int vmstat_open(struct inode *inode, struct file *file) | |||
337 | { | 332 | { |
338 | return seq_open(file, &vmstat_op); | 333 | return seq_open(file, &vmstat_op); |
339 | } | 334 | } |
340 | static struct file_operations proc_vmstat_file_operations = { | 335 | static const struct file_operations proc_vmstat_file_operations = { |
341 | .open = vmstat_open, | 336 | .open = vmstat_open, |
342 | .read = seq_read, | 337 | .read = seq_read, |
343 | .llseek = seq_lseek, | 338 | .llseek = seq_lseek, |
@@ -368,7 +363,7 @@ static int partitions_open(struct inode *inode, struct file *file) | |||
368 | { | 363 | { |
369 | return seq_open(file, &partitions_op); | 364 | return seq_open(file, &partitions_op); |
370 | } | 365 | } |
371 | static struct file_operations proc_partitions_operations = { | 366 | static const struct file_operations proc_partitions_operations = { |
372 | .open = partitions_open, | 367 | .open = partitions_open, |
373 | .read = seq_read, | 368 | .read = seq_read, |
374 | .llseek = seq_lseek, | 369 | .llseek = seq_lseek, |
@@ -380,7 +375,7 @@ static int diskstats_open(struct inode *inode, struct file *file) | |||
380 | { | 375 | { |
381 | return seq_open(file, &diskstats_op); | 376 | return seq_open(file, &diskstats_op); |
382 | } | 377 | } |
383 | static struct file_operations proc_diskstats_operations = { | 378 | static const struct file_operations proc_diskstats_operations = { |
384 | .open = diskstats_open, | 379 | .open = diskstats_open, |
385 | .read = seq_read, | 380 | .read = seq_read, |
386 | .llseek = seq_lseek, | 381 | .llseek = seq_lseek, |
@@ -394,7 +389,7 @@ static int modules_open(struct inode *inode, struct file *file) | |||
394 | { | 389 | { |
395 | return seq_open(file, &modules_op); | 390 | return seq_open(file, &modules_op); |
396 | } | 391 | } |
397 | static struct file_operations proc_modules_operations = { | 392 | static const struct file_operations proc_modules_operations = { |
398 | .open = modules_open, | 393 | .open = modules_open, |
399 | .read = seq_read, | 394 | .read = seq_read, |
400 | .llseek = seq_lseek, | 395 | .llseek = seq_lseek, |
@@ -409,7 +404,7 @@ static int slabinfo_open(struct inode *inode, struct file *file) | |||
409 | { | 404 | { |
410 | return seq_open(file, &slabinfo_op); | 405 | return seq_open(file, &slabinfo_op); |
411 | } | 406 | } |
412 | static struct file_operations proc_slabinfo_operations = { | 407 | static const struct file_operations proc_slabinfo_operations = { |
413 | .open = slabinfo_open, | 408 | .open = slabinfo_open, |
414 | .read = seq_read, | 409 | .read = seq_read, |
415 | .write = slabinfo_write, | 410 | .write = slabinfo_write, |
@@ -443,7 +438,7 @@ static int slabstats_release(struct inode *inode, struct file *file) | |||
443 | return seq_release(inode, file); | 438 | return seq_release(inode, file); |
444 | } | 439 | } |
445 | 440 | ||
446 | static struct file_operations proc_slabstats_operations = { | 441 | static const struct file_operations proc_slabstats_operations = { |
447 | .open = slabstats_open, | 442 | .open = slabstats_open, |
448 | .read = seq_read, | 443 | .read = seq_read, |
449 | .llseek = seq_lseek, | 444 | .llseek = seq_lseek, |
@@ -556,7 +551,7 @@ static int stat_open(struct inode *inode, struct file *file) | |||
556 | kfree(buf); | 551 | kfree(buf); |
557 | return res; | 552 | return res; |
558 | } | 553 | } |
559 | static struct file_operations proc_stat_operations = { | 554 | static const struct file_operations proc_stat_operations = { |
560 | .open = stat_open, | 555 | .open = stat_open, |
561 | .read = seq_read, | 556 | .read = seq_read, |
562 | .llseek = seq_lseek, | 557 | .llseek = seq_lseek, |
@@ -598,7 +593,7 @@ static int interrupts_open(struct inode *inode, struct file *filp) | |||
598 | return seq_open(filp, &int_seq_ops); | 593 | return seq_open(filp, &int_seq_ops); |
599 | } | 594 | } |
600 | 595 | ||
601 | static struct file_operations proc_interrupts_operations = { | 596 | static const struct file_operations proc_interrupts_operations = { |
602 | .open = interrupts_open, | 597 | .open = interrupts_open, |
603 | .read = seq_read, | 598 | .read = seq_read, |
604 | .llseek = seq_lseek, | 599 | .llseek = seq_lseek, |
@@ -655,7 +650,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, | |||
655 | return count; | 650 | return count; |
656 | } | 651 | } |
657 | 652 | ||
658 | static struct file_operations proc_sysrq_trigger_operations = { | 653 | static const struct file_operations proc_sysrq_trigger_operations = { |
659 | .write = write_sysrq_trigger, | 654 | .write = write_sysrq_trigger, |
660 | }; | 655 | }; |
661 | #endif | 656 | #endif |
@@ -672,7 +667,6 @@ void create_seq_entry(char *name, mode_t mode, const struct file_operations *f) | |||
672 | 667 | ||
673 | void __init proc_misc_init(void) | 668 | void __init proc_misc_init(void) |
674 | { | 669 | { |
675 | struct proc_dir_entry *entry; | ||
676 | static struct { | 670 | static struct { |
677 | char *name; | 671 | char *name; |
678 | int (*read_proc)(char*,char**,off_t,int,int*,void*); | 672 | int (*read_proc)(char*,char**,off_t,int,int*,void*); |
@@ -700,9 +694,12 @@ void __init proc_misc_init(void) | |||
700 | 694 | ||
701 | /* And now for trickier ones */ | 695 | /* And now for trickier ones */ |
702 | #ifdef CONFIG_PRINTK | 696 | #ifdef CONFIG_PRINTK |
703 | entry = create_proc_entry("kmsg", S_IRUSR, &proc_root); | 697 | { |
704 | if (entry) | 698 | struct proc_dir_entry *entry; |
705 | entry->proc_fops = &proc_kmsg_operations; | 699 | entry = create_proc_entry("kmsg", S_IRUSR, &proc_root); |
700 | if (entry) | ||
701 | entry->proc_fops = &proc_kmsg_operations; | ||
702 | } | ||
706 | #endif | 703 | #endif |
707 | create_seq_entry("devices", 0, &proc_devinfo_operations); | 704 | create_seq_entry("devices", 0, &proc_devinfo_operations); |
708 | create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); | 705 | create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); |
@@ -743,8 +740,11 @@ void __init proc_misc_init(void) | |||
743 | proc_vmcore->proc_fops = &proc_vmcore_operations; | 740 | proc_vmcore->proc_fops = &proc_vmcore_operations; |
744 | #endif | 741 | #endif |
745 | #ifdef CONFIG_MAGIC_SYSRQ | 742 | #ifdef CONFIG_MAGIC_SYSRQ |
746 | entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL); | 743 | { |
747 | if (entry) | 744 | struct proc_dir_entry *entry; |
748 | entry->proc_fops = &proc_sysrq_trigger_operations; | 745 | entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL); |
746 | if (entry) | ||
747 | entry->proc_fops = &proc_sysrq_trigger_operations; | ||
748 | } | ||
749 | #endif | 749 | #endif |
750 | } | 750 | } |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c new file mode 100644 index 000000000000..20e8cbb34364 --- /dev/null +++ b/fs/proc/proc_sysctl.c | |||
@@ -0,0 +1,479 @@ | |||
1 | /* | ||
2 | * /proc/sys support | ||
3 | */ | ||
4 | |||
5 | #include <linux/sysctl.h> | ||
6 | #include <linux/proc_fs.h> | ||
7 | #include <linux/security.h> | ||
8 | #include "internal.h" | ||
9 | |||
10 | static struct dentry_operations proc_sys_dentry_operations; | ||
11 | static const struct file_operations proc_sys_file_operations; | ||
12 | static struct inode_operations proc_sys_inode_operations; | ||
13 | |||
14 | static void proc_sys_refresh_inode(struct inode *inode, struct ctl_table *table) | ||
15 | { | ||
16 | /* Refresh the cached information bits in the inode */ | ||
17 | if (table) { | ||
18 | inode->i_uid = 0; | ||
19 | inode->i_gid = 0; | ||
20 | inode->i_mode = table->mode; | ||
21 | if (table->proc_handler) { | ||
22 | inode->i_mode |= S_IFREG; | ||
23 | inode->i_nlink = 1; | ||
24 | } else { | ||
25 | inode->i_mode |= S_IFDIR; | ||
26 | inode->i_nlink = 0; /* It is too hard to figure out */ | ||
27 | } | ||
28 | } | ||
29 | } | ||
30 | |||
31 | static struct inode *proc_sys_make_inode(struct inode *dir, struct ctl_table *table) | ||
32 | { | ||
33 | struct inode *inode; | ||
34 | struct proc_inode *dir_ei, *ei; | ||
35 | int depth; | ||
36 | |||
37 | inode = new_inode(dir->i_sb); | ||
38 | if (!inode) | ||
39 | goto out; | ||
40 | |||
41 | /* A directory is always one deeper than it's parent */ | ||
42 | dir_ei = PROC_I(dir); | ||
43 | depth = dir_ei->fd + 1; | ||
44 | |||
45 | ei = PROC_I(inode); | ||
46 | ei->fd = depth; | ||
47 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
48 | inode->i_op = &proc_sys_inode_operations; | ||
49 | inode->i_fop = &proc_sys_file_operations; | ||
50 | inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */ | ||
51 | proc_sys_refresh_inode(inode, table); | ||
52 | out: | ||
53 | return inode; | ||
54 | } | ||
55 | |||
56 | static struct dentry *proc_sys_ancestor(struct dentry *dentry, int depth) | ||
57 | { | ||
58 | for (;;) { | ||
59 | struct proc_inode *ei; | ||
60 | |||
61 | ei = PROC_I(dentry->d_inode); | ||
62 | if (ei->fd == depth) | ||
63 | break; /* found */ | ||
64 | |||
65 | dentry = dentry->d_parent; | ||
66 | } | ||
67 | return dentry; | ||
68 | } | ||
69 | |||
70 | static struct ctl_table *proc_sys_lookup_table_one(struct ctl_table *table, | ||
71 | struct qstr *name) | ||
72 | { | ||
73 | int len; | ||
74 | for ( ; table->ctl_name || table->procname; table++) { | ||
75 | |||
76 | if (!table->procname) | ||
77 | continue; | ||
78 | |||
79 | len = strlen(table->procname); | ||
80 | if (len != name->len) | ||
81 | continue; | ||
82 | |||
83 | if (memcmp(table->procname, name->name, len) != 0) | ||
84 | continue; | ||
85 | |||
86 | /* I have a match */ | ||
87 | return table; | ||
88 | } | ||
89 | return NULL; | ||
90 | } | ||
91 | |||
92 | static struct ctl_table *proc_sys_lookup_table(struct dentry *dentry, | ||
93 | struct ctl_table *table) | ||
94 | { | ||
95 | struct dentry *ancestor; | ||
96 | struct proc_inode *ei; | ||
97 | int depth, i; | ||
98 | |||
99 | ei = PROC_I(dentry->d_inode); | ||
100 | depth = ei->fd; | ||
101 | |||
102 | if (depth == 0) | ||
103 | return table; | ||
104 | |||
105 | for (i = 1; table && (i <= depth); i++) { | ||
106 | ancestor = proc_sys_ancestor(dentry, i); | ||
107 | table = proc_sys_lookup_table_one(table, &ancestor->d_name); | ||
108 | if (table) | ||
109 | table = table->child; | ||
110 | } | ||
111 | return table; | ||
112 | |||
113 | } | ||
114 | static struct ctl_table *proc_sys_lookup_entry(struct dentry *dparent, | ||
115 | struct qstr *name, | ||
116 | struct ctl_table *table) | ||
117 | { | ||
118 | table = proc_sys_lookup_table(dparent, table); | ||
119 | if (table) | ||
120 | table = proc_sys_lookup_table_one(table, name); | ||
121 | return table; | ||
122 | } | ||
123 | |||
124 | static struct ctl_table *do_proc_sys_lookup(struct dentry *parent, | ||
125 | struct qstr *name, | ||
126 | struct ctl_table_header **ptr) | ||
127 | { | ||
128 | struct ctl_table_header *head; | ||
129 | struct ctl_table *table = NULL; | ||
130 | |||
131 | for (head = sysctl_head_next(NULL); head; | ||
132 | head = sysctl_head_next(head)) { | ||
133 | table = proc_sys_lookup_entry(parent, name, head->ctl_table); | ||
134 | if (table) | ||
135 | break; | ||
136 | } | ||
137 | *ptr = head; | ||
138 | return table; | ||
139 | } | ||
140 | |||
141 | static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, | ||
142 | struct nameidata *nd) | ||
143 | { | ||
144 | struct ctl_table_header *head; | ||
145 | struct inode *inode; | ||
146 | struct dentry *err; | ||
147 | struct ctl_table *table; | ||
148 | |||
149 | err = ERR_PTR(-ENOENT); | ||
150 | table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); | ||
151 | if (!table) | ||
152 | goto out; | ||
153 | |||
154 | err = ERR_PTR(-ENOMEM); | ||
155 | inode = proc_sys_make_inode(dir, table); | ||
156 | if (!inode) | ||
157 | goto out; | ||
158 | |||
159 | err = NULL; | ||
160 | dentry->d_op = &proc_sys_dentry_operations; | ||
161 | d_add(dentry, inode); | ||
162 | |||
163 | out: | ||
164 | sysctl_head_finish(head); | ||
165 | return err; | ||
166 | } | ||
167 | |||
168 | static ssize_t proc_sys_read(struct file *filp, char __user *buf, | ||
169 | size_t count, loff_t *ppos) | ||
170 | { | ||
171 | struct dentry *dentry = filp->f_dentry; | ||
172 | struct ctl_table_header *head; | ||
173 | struct ctl_table *table; | ||
174 | ssize_t error, res; | ||
175 | |||
176 | table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); | ||
177 | /* Has the sysctl entry disappeared on us? */ | ||
178 | error = -ENOENT; | ||
179 | if (!table) | ||
180 | goto out; | ||
181 | |||
182 | /* Has the sysctl entry been replaced by a directory? */ | ||
183 | error = -EISDIR; | ||
184 | if (!table->proc_handler) | ||
185 | goto out; | ||
186 | |||
187 | /* | ||
188 | * At this point we know that the sysctl was not unregistered | ||
189 | * and won't be until we finish. | ||
190 | */ | ||
191 | error = -EPERM; | ||
192 | if (sysctl_perm(table, MAY_READ)) | ||
193 | goto out; | ||
194 | |||
195 | /* careful: calling conventions are nasty here */ | ||
196 | res = count; | ||
197 | error = table->proc_handler(table, 0, filp, buf, &res, ppos); | ||
198 | if (!error) | ||
199 | error = res; | ||
200 | out: | ||
201 | sysctl_head_finish(head); | ||
202 | |||
203 | return error; | ||
204 | } | ||
205 | |||
206 | static ssize_t proc_sys_write(struct file *filp, const char __user *buf, | ||
207 | size_t count, loff_t *ppos) | ||
208 | { | ||
209 | struct dentry *dentry = filp->f_dentry; | ||
210 | struct ctl_table_header *head; | ||
211 | struct ctl_table *table; | ||
212 | ssize_t error, res; | ||
213 | |||
214 | table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); | ||
215 | /* Has the sysctl entry disappeared on us? */ | ||
216 | error = -ENOENT; | ||
217 | if (!table) | ||
218 | goto out; | ||
219 | |||
220 | /* Has the sysctl entry been replaced by a directory? */ | ||
221 | error = -EISDIR; | ||
222 | if (!table->proc_handler) | ||
223 | goto out; | ||
224 | |||
225 | /* | ||
226 | * At this point we know that the sysctl was not unregistered | ||
227 | * and won't be until we finish. | ||
228 | */ | ||
229 | error = -EPERM; | ||
230 | if (sysctl_perm(table, MAY_WRITE)) | ||
231 | goto out; | ||
232 | |||
233 | /* careful: calling conventions are nasty here */ | ||
234 | res = count; | ||
235 | error = table->proc_handler(table, 1, filp, (char __user *)buf, | ||
236 | &res, ppos); | ||
237 | if (!error) | ||
238 | error = res; | ||
239 | out: | ||
240 | sysctl_head_finish(head); | ||
241 | |||
242 | return error; | ||
243 | } | ||
244 | |||
245 | |||
246 | static int proc_sys_fill_cache(struct file *filp, void *dirent, | ||
247 | filldir_t filldir, struct ctl_table *table) | ||
248 | { | ||
249 | struct ctl_table_header *head; | ||
250 | struct ctl_table *child_table = NULL; | ||
251 | struct dentry *child, *dir = filp->f_path.dentry; | ||
252 | struct inode *inode; | ||
253 | struct qstr qname; | ||
254 | ino_t ino = 0; | ||
255 | unsigned type = DT_UNKNOWN; | ||
256 | int ret; | ||
257 | |||
258 | qname.name = table->procname; | ||
259 | qname.len = strlen(table->procname); | ||
260 | qname.hash = full_name_hash(qname.name, qname.len); | ||
261 | |||
262 | /* Suppress duplicates. | ||
263 | * Only fill a directory entry if it is the value that | ||
264 | * an ordinary lookup of that name returns. Hide all | ||
265 | * others. | ||
266 | * | ||
267 | * If we ever cache this translation in the dcache | ||
268 | * I should do a dcache lookup first. But for now | ||
269 | * it is just simpler not to. | ||
270 | */ | ||
271 | ret = 0; | ||
272 | child_table = do_proc_sys_lookup(dir, &qname, &head); | ||
273 | sysctl_head_finish(head); | ||
274 | if (child_table != table) | ||
275 | return 0; | ||
276 | |||
277 | child = d_lookup(dir, &qname); | ||
278 | if (!child) { | ||
279 | struct dentry *new; | ||
280 | new = d_alloc(dir, &qname); | ||
281 | if (new) { | ||
282 | inode = proc_sys_make_inode(dir->d_inode, table); | ||
283 | if (!inode) | ||
284 | child = ERR_PTR(-ENOMEM); | ||
285 | else { | ||
286 | new->d_op = &proc_sys_dentry_operations; | ||
287 | d_add(new, inode); | ||
288 | } | ||
289 | if (child) | ||
290 | dput(new); | ||
291 | else | ||
292 | child = new; | ||
293 | } | ||
294 | } | ||
295 | if (!child || IS_ERR(child) || !child->d_inode) | ||
296 | goto end_instantiate; | ||
297 | inode = child->d_inode; | ||
298 | if (inode) { | ||
299 | ino = inode->i_ino; | ||
300 | type = inode->i_mode >> 12; | ||
301 | } | ||
302 | dput(child); | ||
303 | end_instantiate: | ||
304 | if (!ino) | ||
305 | ino= find_inode_number(dir, &qname); | ||
306 | if (!ino) | ||
307 | ino = 1; | ||
308 | return filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type); | ||
309 | } | ||
310 | |||
311 | static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
312 | { | ||
313 | struct dentry *dentry = filp->f_dentry; | ||
314 | struct inode *inode = dentry->d_inode; | ||
315 | struct ctl_table_header *head = NULL; | ||
316 | struct ctl_table *table; | ||
317 | unsigned long pos; | ||
318 | int ret; | ||
319 | |||
320 | ret = -ENOTDIR; | ||
321 | if (!S_ISDIR(inode->i_mode)) | ||
322 | goto out; | ||
323 | |||
324 | ret = 0; | ||
325 | /* Avoid a switch here: arm builds fail with missing __cmpdi2 */ | ||
326 | if (filp->f_pos == 0) { | ||
327 | if (filldir(dirent, ".", 1, filp->f_pos, | ||
328 | inode->i_ino, DT_DIR) < 0) | ||
329 | goto out; | ||
330 | filp->f_pos++; | ||
331 | } | ||
332 | if (filp->f_pos == 1) { | ||
333 | if (filldir(dirent, "..", 2, filp->f_pos, | ||
334 | parent_ino(dentry), DT_DIR) < 0) | ||
335 | goto out; | ||
336 | filp->f_pos++; | ||
337 | } | ||
338 | pos = 2; | ||
339 | |||
340 | /* - Find each instance of the directory | ||
341 | * - Read all entries in each instance | ||
342 | * - Before returning an entry to user space lookup the entry | ||
343 | * by name and if I find a different entry don't return | ||
344 | * this one because it means it is a buried dup. | ||
345 | * For sysctl this should only happen for directory entries. | ||
346 | */ | ||
347 | for (head = sysctl_head_next(NULL); head; head = sysctl_head_next(head)) { | ||
348 | table = proc_sys_lookup_table(dentry, head->ctl_table); | ||
349 | |||
350 | if (!table) | ||
351 | continue; | ||
352 | |||
353 | for (; table->ctl_name || table->procname; table++, pos++) { | ||
354 | /* Can't do anything without a proc name */ | ||
355 | if (!table->procname) | ||
356 | continue; | ||
357 | |||
358 | if (pos < filp->f_pos) | ||
359 | continue; | ||
360 | |||
361 | if (proc_sys_fill_cache(filp, dirent, filldir, table) < 0) | ||
362 | goto out; | ||
363 | filp->f_pos = pos + 1; | ||
364 | } | ||
365 | } | ||
366 | ret = 1; | ||
367 | out: | ||
368 | sysctl_head_finish(head); | ||
369 | return ret; | ||
370 | } | ||
371 | |||
372 | static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *nd) | ||
373 | { | ||
374 | /* | ||
375 | * sysctl entries that are not writeable, | ||
376 | * are _NOT_ writeable, capabilities or not. | ||
377 | */ | ||
378 | struct ctl_table_header *head; | ||
379 | struct ctl_table *table; | ||
380 | struct dentry *dentry; | ||
381 | int mode; | ||
382 | int depth; | ||
383 | int error; | ||
384 | |||
385 | head = NULL; | ||
386 | depth = PROC_I(inode)->fd; | ||
387 | |||
388 | /* First check the cached permissions, in case we don't have | ||
389 | * enough information to lookup the sysctl table entry. | ||
390 | */ | ||
391 | error = -EACCES; | ||
392 | mode = inode->i_mode; | ||
393 | |||
394 | if (current->euid == 0) | ||
395 | mode >>= 6; | ||
396 | else if (in_group_p(0)) | ||
397 | mode >>= 3; | ||
398 | |||
399 | if ((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask) | ||
400 | error = 0; | ||
401 | |||
402 | /* If we can't get a sysctl table entry the permission | ||
403 | * checks on the cached mode will have to be enough. | ||
404 | */ | ||
405 | if (!nd || !depth) | ||
406 | goto out; | ||
407 | |||
408 | dentry = nd->dentry; | ||
409 | table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); | ||
410 | |||
411 | /* If the entry does not exist deny permission */ | ||
412 | error = -EACCES; | ||
413 | if (!table) | ||
414 | goto out; | ||
415 | |||
416 | /* Use the permissions on the sysctl table entry */ | ||
417 | error = sysctl_perm(table, mask); | ||
418 | out: | ||
419 | sysctl_head_finish(head); | ||
420 | return error; | ||
421 | } | ||
422 | |||
423 | static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr) | ||
424 | { | ||
425 | struct inode *inode = dentry->d_inode; | ||
426 | int error; | ||
427 | |||
428 | if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) | ||
429 | return -EPERM; | ||
430 | |||
431 | error = inode_change_ok(inode, attr); | ||
432 | if (!error) { | ||
433 | error = security_inode_setattr(dentry, attr); | ||
434 | if (!error) | ||
435 | error = inode_setattr(inode, attr); | ||
436 | } | ||
437 | |||
438 | return error; | ||
439 | } | ||
440 | |||
441 | /* I'm lazy and don't distinguish between files and directories, | ||
442 | * until access time. | ||
443 | */ | ||
444 | static const struct file_operations proc_sys_file_operations = { | ||
445 | .read = proc_sys_read, | ||
446 | .write = proc_sys_write, | ||
447 | .readdir = proc_sys_readdir, | ||
448 | }; | ||
449 | |||
450 | static struct inode_operations proc_sys_inode_operations = { | ||
451 | .lookup = proc_sys_lookup, | ||
452 | .permission = proc_sys_permission, | ||
453 | .setattr = proc_sys_setattr, | ||
454 | }; | ||
455 | |||
456 | static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
457 | { | ||
458 | struct ctl_table_header *head; | ||
459 | struct ctl_table *table; | ||
460 | table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); | ||
461 | proc_sys_refresh_inode(dentry->d_inode, table); | ||
462 | sysctl_head_finish(head); | ||
463 | return !!table; | ||
464 | } | ||
465 | |||
466 | static struct dentry_operations proc_sys_dentry_operations = { | ||
467 | .d_revalidate = proc_sys_revalidate, | ||
468 | }; | ||
469 | |||
470 | static struct proc_dir_entry *proc_sys_root; | ||
471 | |||
472 | int proc_sys_init(void) | ||
473 | { | ||
474 | proc_sys_root = proc_mkdir("sys", NULL); | ||
475 | proc_sys_root->proc_iops = &proc_sys_inode_operations; | ||
476 | proc_sys_root->proc_fops = &proc_sys_file_operations; | ||
477 | proc_sys_root->nlink = 0; | ||
478 | return 0; | ||
479 | } | ||
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index 15c4455b09eb..c1bbfbeb035e 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c | |||
@@ -138,7 +138,7 @@ static int tty_drivers_open(struct inode *inode, struct file *file) | |||
138 | return seq_open(file, &tty_drivers_op); | 138 | return seq_open(file, &tty_drivers_op); |
139 | } | 139 | } |
140 | 140 | ||
141 | static struct file_operations proc_tty_drivers_operations = { | 141 | static const struct file_operations proc_tty_drivers_operations = { |
142 | .open = tty_drivers_open, | 142 | .open = tty_drivers_open, |
143 | .read = seq_read, | 143 | .read = seq_read, |
144 | .llseek = seq_lseek, | 144 | .llseek = seq_lseek, |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 64d242b6dcfa..5834a744c2a9 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -23,10 +23,6 @@ | |||
23 | 23 | ||
24 | struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver; | 24 | struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver; |
25 | 25 | ||
26 | #ifdef CONFIG_SYSCTL | ||
27 | struct proc_dir_entry *proc_sys_root; | ||
28 | #endif | ||
29 | |||
30 | static int proc_get_sb(struct file_system_type *fs_type, | 26 | static int proc_get_sb(struct file_system_type *fs_type, |
31 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 27 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
32 | { | 28 | { |
@@ -71,13 +67,6 @@ void __init proc_root_init(void) | |||
71 | #ifdef CONFIG_SYSVIPC | 67 | #ifdef CONFIG_SYSVIPC |
72 | proc_mkdir("sysvipc", NULL); | 68 | proc_mkdir("sysvipc", NULL); |
73 | #endif | 69 | #endif |
74 | #ifdef CONFIG_SYSCTL | ||
75 | proc_sys_root = proc_mkdir("sys", NULL); | ||
76 | #endif | ||
77 | #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE) | ||
78 | proc_mkdir("sys/fs", NULL); | ||
79 | proc_mkdir("sys/fs/binfmt_misc", NULL); | ||
80 | #endif | ||
81 | proc_root_fs = proc_mkdir("fs", NULL); | 70 | proc_root_fs = proc_mkdir("fs", NULL); |
82 | proc_root_driver = proc_mkdir("driver", NULL); | 71 | proc_root_driver = proc_mkdir("driver", NULL); |
83 | proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */ | 72 | proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */ |
@@ -90,6 +79,9 @@ void __init proc_root_init(void) | |||
90 | proc_device_tree_init(); | 79 | proc_device_tree_init(); |
91 | #endif | 80 | #endif |
92 | proc_bus = proc_mkdir("bus", NULL); | 81 | proc_bus = proc_mkdir("bus", NULL); |
82 | #ifdef CONFIG_SYSCTL | ||
83 | proc_sys_init(); | ||
84 | #endif | ||
93 | } | 85 | } |
94 | 86 | ||
95 | static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat | 87 | static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat |
@@ -136,7 +128,7 @@ static int proc_root_readdir(struct file * filp, | |||
136 | * <pid> directories. Thus we don't use the generic | 128 | * <pid> directories. Thus we don't use the generic |
137 | * directory handling functions for that.. | 129 | * directory handling functions for that.. |
138 | */ | 130 | */ |
139 | static struct file_operations proc_root_operations = { | 131 | static const struct file_operations proc_root_operations = { |
140 | .read = generic_read_dir, | 132 | .read = generic_read_dir, |
141 | .readdir = proc_root_readdir, | 133 | .readdir = proc_root_readdir, |
142 | }; | 134 | }; |
@@ -144,7 +136,7 @@ static struct file_operations proc_root_operations = { | |||
144 | /* | 136 | /* |
145 | * proc root can do almost nothing.. | 137 | * proc root can do almost nothing.. |
146 | */ | 138 | */ |
147 | static struct inode_operations proc_root_inode_operations = { | 139 | static const struct inode_operations proc_root_inode_operations = { |
148 | .lookup = proc_root_lookup, | 140 | .lookup = proc_root_lookup, |
149 | .getattr = proc_root_getattr, | 141 | .getattr = proc_root_getattr, |
150 | }; | 142 | }; |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 55ade0d15621..7445980c8022 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -434,7 +434,7 @@ static int maps_open(struct inode *inode, struct file *file) | |||
434 | return do_maps_open(inode, file, &proc_pid_maps_op); | 434 | return do_maps_open(inode, file, &proc_pid_maps_op); |
435 | } | 435 | } |
436 | 436 | ||
437 | struct file_operations proc_maps_operations = { | 437 | const struct file_operations proc_maps_operations = { |
438 | .open = maps_open, | 438 | .open = maps_open, |
439 | .read = seq_read, | 439 | .read = seq_read, |
440 | .llseek = seq_lseek, | 440 | .llseek = seq_lseek, |
@@ -456,7 +456,7 @@ static int numa_maps_open(struct inode *inode, struct file *file) | |||
456 | return do_maps_open(inode, file, &proc_pid_numa_maps_op); | 456 | return do_maps_open(inode, file, &proc_pid_numa_maps_op); |
457 | } | 457 | } |
458 | 458 | ||
459 | struct file_operations proc_numa_maps_operations = { | 459 | const struct file_operations proc_numa_maps_operations = { |
460 | .open = numa_maps_open, | 460 | .open = numa_maps_open, |
461 | .read = seq_read, | 461 | .read = seq_read, |
462 | .llseek = seq_lseek, | 462 | .llseek = seq_lseek, |
@@ -469,7 +469,7 @@ static int smaps_open(struct inode *inode, struct file *file) | |||
469 | return do_maps_open(inode, file, &proc_pid_smaps_op); | 469 | return do_maps_open(inode, file, &proc_pid_smaps_op); |
470 | } | 470 | } |
471 | 471 | ||
472 | struct file_operations proc_smaps_operations = { | 472 | const struct file_operations proc_smaps_operations = { |
473 | .open = smaps_open, | 473 | .open = smaps_open, |
474 | .read = seq_read, | 474 | .read = seq_read, |
475 | .llseek = seq_lseek, | 475 | .llseek = seq_lseek, |
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index fcc5caf93f55..7cddf6b8635a 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c | |||
@@ -220,7 +220,7 @@ static int maps_open(struct inode *inode, struct file *file) | |||
220 | return ret; | 220 | return ret; |
221 | } | 221 | } |
222 | 222 | ||
223 | struct file_operations proc_maps_operations = { | 223 | const struct file_operations proc_maps_operations = { |
224 | .open = maps_open, | 224 | .open = maps_open, |
225 | .read = seq_read, | 225 | .read = seq_read, |
226 | .llseek = seq_lseek, | 226 | .llseek = seq_lseek, |
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c index c94db1db7a71..ea9ffefb48ad 100644 --- a/fs/qnx4/dir.c +++ b/fs/qnx4/dir.c | |||
@@ -87,7 +87,7 @@ const struct file_operations qnx4_dir_operations = | |||
87 | .fsync = file_fsync, | 87 | .fsync = file_fsync, |
88 | }; | 88 | }; |
89 | 89 | ||
90 | struct inode_operations qnx4_dir_inode_operations = | 90 | const struct inode_operations qnx4_dir_inode_operations = |
91 | { | 91 | { |
92 | .lookup = qnx4_lookup, | 92 | .lookup = qnx4_lookup, |
93 | #ifdef CONFIG_QNX4FS_RW | 93 | #ifdef CONFIG_QNX4FS_RW |
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c index 467e5ac7280e..44649981bbc8 100644 --- a/fs/qnx4/file.c +++ b/fs/qnx4/file.c | |||
@@ -33,7 +33,7 @@ const struct file_operations qnx4_file_operations = | |||
33 | #endif | 33 | #endif |
34 | }; | 34 | }; |
35 | 35 | ||
36 | struct inode_operations qnx4_file_inode_operations = | 36 | const struct inode_operations qnx4_file_inode_operations = |
37 | { | 37 | { |
38 | #ifdef CONFIG_QNX4FS_RW | 38 | #ifdef CONFIG_QNX4FS_RW |
39 | .truncate = qnx4_truncate, | 39 | .truncate = qnx4_truncate, |
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index c047dc654d5c..83bc8e7824cd 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #define QNX4_VERSION 4 | 30 | #define QNX4_VERSION 4 |
31 | #define QNX4_BMNAME ".bitmap" | 31 | #define QNX4_BMNAME ".bitmap" |
32 | 32 | ||
33 | static struct super_operations qnx4_sops; | 33 | static const struct super_operations qnx4_sops; |
34 | 34 | ||
35 | #ifdef CONFIG_QNX4FS_RW | 35 | #ifdef CONFIG_QNX4FS_RW |
36 | 36 | ||
@@ -129,7 +129,7 @@ static void qnx4_read_inode(struct inode *); | |||
129 | static int qnx4_remount(struct super_block *sb, int *flags, char *data); | 129 | static int qnx4_remount(struct super_block *sb, int *flags, char *data); |
130 | static int qnx4_statfs(struct dentry *, struct kstatfs *); | 130 | static int qnx4_statfs(struct dentry *, struct kstatfs *); |
131 | 131 | ||
132 | static struct super_operations qnx4_sops = | 132 | static const struct super_operations qnx4_sops = |
133 | { | 133 | { |
134 | .alloc_inode = qnx4_alloc_inode, | 134 | .alloc_inode = qnx4_alloc_inode, |
135 | .destroy_inode = qnx4_destroy_inode, | 135 | .destroy_inode = qnx4_destroy_inode, |
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c index 54ebbc84207f..2f14774a124f 100644 --- a/fs/ramfs/file-mmu.c +++ b/fs/ramfs/file-mmu.c | |||
@@ -31,7 +31,7 @@ const struct address_space_operations ramfs_aops = { | |||
31 | .readpage = simple_readpage, | 31 | .readpage = simple_readpage, |
32 | .prepare_write = simple_prepare_write, | 32 | .prepare_write = simple_prepare_write, |
33 | .commit_write = simple_commit_write, | 33 | .commit_write = simple_commit_write, |
34 | .set_page_dirty = __set_page_dirty_nobuffers, | 34 | .set_page_dirty = __set_page_dirty_no_writeback, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | const struct file_operations ramfs_file_operations = { | 37 | const struct file_operations ramfs_file_operations = { |
@@ -45,6 +45,6 @@ const struct file_operations ramfs_file_operations = { | |||
45 | .llseek = generic_file_llseek, | 45 | .llseek = generic_file_llseek, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | struct inode_operations ramfs_file_inode_operations = { | 48 | const struct inode_operations ramfs_file_inode_operations = { |
49 | .getattr = simple_getattr, | 49 | .getattr = simple_getattr, |
50 | }; | 50 | }; |
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index e9d6c4733282..d3fd7c6732d2 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
@@ -32,7 +32,7 @@ const struct address_space_operations ramfs_aops = { | |||
32 | .readpage = simple_readpage, | 32 | .readpage = simple_readpage, |
33 | .prepare_write = simple_prepare_write, | 33 | .prepare_write = simple_prepare_write, |
34 | .commit_write = simple_commit_write, | 34 | .commit_write = simple_commit_write, |
35 | .set_page_dirty = __set_page_dirty_nobuffers, | 35 | .set_page_dirty = __set_page_dirty_no_writeback, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | const struct file_operations ramfs_file_operations = { | 38 | const struct file_operations ramfs_file_operations = { |
@@ -47,7 +47,7 @@ const struct file_operations ramfs_file_operations = { | |||
47 | .llseek = generic_file_llseek, | 47 | .llseek = generic_file_llseek, |
48 | }; | 48 | }; |
49 | 49 | ||
50 | struct inode_operations ramfs_file_inode_operations = { | 50 | const struct inode_operations ramfs_file_inode_operations = { |
51 | .setattr = ramfs_nommu_setattr, | 51 | .setattr = ramfs_nommu_setattr, |
52 | .getattr = simple_getattr, | 52 | .getattr = simple_getattr, |
53 | }; | 53 | }; |
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 2faf4cdf61b0..ff1f7639707b 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c | |||
@@ -40,8 +40,8 @@ | |||
40 | /* some random number */ | 40 | /* some random number */ |
41 | #define RAMFS_MAGIC 0x858458f6 | 41 | #define RAMFS_MAGIC 0x858458f6 |
42 | 42 | ||
43 | static struct super_operations ramfs_ops; | 43 | static const struct super_operations ramfs_ops; |
44 | static struct inode_operations ramfs_dir_inode_operations; | 44 | static const struct inode_operations ramfs_dir_inode_operations; |
45 | 45 | ||
46 | static struct backing_dev_info ramfs_backing_dev_info = { | 46 | static struct backing_dev_info ramfs_backing_dev_info = { |
47 | .ra_pages = 0, /* No readahead */ | 47 | .ra_pages = 0, /* No readahead */ |
@@ -143,7 +143,7 @@ static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * | |||
143 | return error; | 143 | return error; |
144 | } | 144 | } |
145 | 145 | ||
146 | static struct inode_operations ramfs_dir_inode_operations = { | 146 | static const struct inode_operations ramfs_dir_inode_operations = { |
147 | .create = ramfs_create, | 147 | .create = ramfs_create, |
148 | .lookup = simple_lookup, | 148 | .lookup = simple_lookup, |
149 | .link = simple_link, | 149 | .link = simple_link, |
@@ -155,7 +155,7 @@ static struct inode_operations ramfs_dir_inode_operations = { | |||
155 | .rename = simple_rename, | 155 | .rename = simple_rename, |
156 | }; | 156 | }; |
157 | 157 | ||
158 | static struct super_operations ramfs_ops = { | 158 | static const struct super_operations ramfs_ops = { |
159 | .statfs = simple_statfs, | 159 | .statfs = simple_statfs, |
160 | .drop_inode = generic_delete_inode, | 160 | .drop_inode = generic_delete_inode, |
161 | }; | 161 | }; |
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h index c2bb58e74653..af7cc074a476 100644 --- a/fs/ramfs/internal.h +++ b/fs/ramfs/internal.h | |||
@@ -12,4 +12,4 @@ | |||
12 | 12 | ||
13 | extern const struct address_space_operations ramfs_aops; | 13 | extern const struct address_space_operations ramfs_aops; |
14 | extern const struct file_operations ramfs_file_operations; | 14 | extern const struct file_operations ramfs_file_operations; |
15 | extern struct inode_operations ramfs_file_inode_operations; | 15 | extern const struct inode_operations ramfs_file_inode_operations; |
diff --git a/fs/read_write.c b/fs/read_write.c index 707ac21700d3..1f8dc373ede7 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -197,13 +197,13 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count | |||
197 | struct inode *inode; | 197 | struct inode *inode; |
198 | loff_t pos; | 198 | loff_t pos; |
199 | 199 | ||
200 | inode = file->f_path.dentry->d_inode; | ||
200 | if (unlikely((ssize_t) count < 0)) | 201 | if (unlikely((ssize_t) count < 0)) |
201 | goto Einval; | 202 | goto Einval; |
202 | pos = *ppos; | 203 | pos = *ppos; |
203 | if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) | 204 | if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) |
204 | goto Einval; | 205 | goto Einval; |
205 | 206 | ||
206 | inode = file->f_path.dentry->d_inode; | ||
207 | if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) { | 207 | if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) { |
208 | int retval = locks_mandatory_area( | 208 | int retval = locks_mandatory_area( |
209 | read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, | 209 | read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, |
@@ -274,9 +274,9 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) | |||
274 | ret = do_sync_read(file, buf, count, pos); | 274 | ret = do_sync_read(file, buf, count, pos); |
275 | if (ret > 0) { | 275 | if (ret > 0) { |
276 | fsnotify_access(file->f_path.dentry); | 276 | fsnotify_access(file->f_path.dentry); |
277 | current->rchar += ret; | 277 | add_rchar(current, ret); |
278 | } | 278 | } |
279 | current->syscr++; | 279 | inc_syscr(current); |
280 | } | 280 | } |
281 | } | 281 | } |
282 | 282 | ||
@@ -332,9 +332,9 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ | |||
332 | ret = do_sync_write(file, buf, count, pos); | 332 | ret = do_sync_write(file, buf, count, pos); |
333 | if (ret > 0) { | 333 | if (ret > 0) { |
334 | fsnotify_modify(file->f_path.dentry); | 334 | fsnotify_modify(file->f_path.dentry); |
335 | current->wchar += ret; | 335 | add_wchar(current, ret); |
336 | } | 336 | } |
337 | current->syscw++; | 337 | inc_syscw(current); |
338 | } | 338 | } |
339 | } | 339 | } |
340 | 340 | ||
@@ -675,8 +675,8 @@ sys_readv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen) | |||
675 | } | 675 | } |
676 | 676 | ||
677 | if (ret > 0) | 677 | if (ret > 0) |
678 | current->rchar += ret; | 678 | add_rchar(current, ret); |
679 | current->syscr++; | 679 | inc_syscr(current); |
680 | return ret; | 680 | return ret; |
681 | } | 681 | } |
682 | 682 | ||
@@ -696,8 +696,8 @@ sys_writev(unsigned long fd, const struct iovec __user *vec, unsigned long vlen) | |||
696 | } | 696 | } |
697 | 697 | ||
698 | if (ret > 0) | 698 | if (ret > 0) |
699 | current->wchar += ret; | 699 | add_wchar(current, ret); |
700 | current->syscw++; | 700 | inc_syscw(current); |
701 | return ret; | 701 | return ret; |
702 | } | 702 | } |
703 | 703 | ||
@@ -779,12 +779,12 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
779 | retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file); | 779 | retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file); |
780 | 780 | ||
781 | if (retval > 0) { | 781 | if (retval > 0) { |
782 | current->rchar += retval; | 782 | add_rchar(current, retval); |
783 | current->wchar += retval; | 783 | add_wchar(current, retval); |
784 | } | 784 | } |
785 | current->syscr++; | ||
786 | current->syscw++; | ||
787 | 785 | ||
786 | inc_syscr(current); | ||
787 | inc_syscw(current); | ||
788 | if (*ppos > max) | 788 | if (*ppos > max) |
789 | retval = -EOVERFLOW; | 789 | retval = -EOVERFLOW; |
790 | 790 | ||
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index fba304e64de8..f85c5cf4934c 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/time.h> | 19 | #include <linux/time.h> |
20 | #include <linux/reiserfs_fs.h> | 20 | #include <linux/reiserfs_fs.h> |
21 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
22 | #include <linux/kernel.h> | ||
22 | 23 | ||
23 | #ifdef CONFIG_REISERFS_CHECK | 24 | #ifdef CONFIG_REISERFS_CHECK |
24 | 25 | ||
@@ -1756,7 +1757,7 @@ static void store_thrown(struct tree_balance *tb, struct buffer_head *bh) | |||
1756 | if (buffer_dirty(bh)) | 1757 | if (buffer_dirty(bh)) |
1757 | reiserfs_warning(tb->tb_sb, | 1758 | reiserfs_warning(tb->tb_sb, |
1758 | "store_thrown deals with dirty buffer"); | 1759 | "store_thrown deals with dirty buffer"); |
1759 | for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++) | 1760 | for (i = 0; i < ARRAY_SIZE(tb->thrown); i++) |
1760 | if (!tb->thrown[i]) { | 1761 | if (!tb->thrown[i]) { |
1761 | tb->thrown[i] = bh; | 1762 | tb->thrown[i] = bh; |
1762 | get_bh(bh); /* free_thrown puts this */ | 1763 | get_bh(bh); /* free_thrown puts this */ |
@@ -1769,7 +1770,7 @@ static void free_thrown(struct tree_balance *tb) | |||
1769 | { | 1770 | { |
1770 | int i; | 1771 | int i; |
1771 | b_blocknr_t blocknr; | 1772 | b_blocknr_t blocknr; |
1772 | for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++) { | 1773 | for (i = 0; i < ARRAY_SIZE(tb->thrown); i++) { |
1773 | if (tb->thrown[i]) { | 1774 | if (tb->thrown[i]) { |
1774 | blocknr = tb->thrown[i]->b_blocknr; | 1775 | blocknr = tb->thrown[i]->b_blocknr; |
1775 | if (buffer_dirty(tb->thrown[i])) | 1776 | if (buffer_dirty(tb->thrown[i])) |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 5109f1d5e7ff..abfada2f52db 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
@@ -1556,7 +1556,7 @@ const struct file_operations reiserfs_file_operations = { | |||
1556 | .splice_write = generic_file_splice_write, | 1556 | .splice_write = generic_file_splice_write, |
1557 | }; | 1557 | }; |
1558 | 1558 | ||
1559 | struct inode_operations reiserfs_file_inode_operations = { | 1559 | const struct inode_operations reiserfs_file_inode_operations = { |
1560 | .truncate = reiserfs_vfs_truncate_file, | 1560 | .truncate = reiserfs_vfs_truncate_file, |
1561 | .setattr = reiserfs_setattr, | 1561 | .setattr = reiserfs_setattr, |
1562 | .setxattr = reiserfs_setxattr, | 1562 | .setxattr = reiserfs_setxattr, |
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 23f5cd5bbf56..a2161840bc7c 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
@@ -1525,7 +1525,7 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1525 | /* | 1525 | /* |
1526 | * directories can handle most operations... | 1526 | * directories can handle most operations... |
1527 | */ | 1527 | */ |
1528 | struct inode_operations reiserfs_dir_inode_operations = { | 1528 | const struct inode_operations reiserfs_dir_inode_operations = { |
1529 | //&reiserfs_dir_operations, /* default_file_ops */ | 1529 | //&reiserfs_dir_operations, /* default_file_ops */ |
1530 | .create = reiserfs_create, | 1530 | .create = reiserfs_create, |
1531 | .lookup = reiserfs_lookup, | 1531 | .lookup = reiserfs_lookup, |
@@ -1548,7 +1548,7 @@ struct inode_operations reiserfs_dir_inode_operations = { | |||
1548 | * symlink operations.. same as page_symlink_inode_operations, with xattr | 1548 | * symlink operations.. same as page_symlink_inode_operations, with xattr |
1549 | * stuff added | 1549 | * stuff added |
1550 | */ | 1550 | */ |
1551 | struct inode_operations reiserfs_symlink_inode_operations = { | 1551 | const struct inode_operations reiserfs_symlink_inode_operations = { |
1552 | .readlink = generic_readlink, | 1552 | .readlink = generic_readlink, |
1553 | .follow_link = page_follow_link_light, | 1553 | .follow_link = page_follow_link_light, |
1554 | .put_link = page_put_link, | 1554 | .put_link = page_put_link, |
@@ -1564,7 +1564,7 @@ struct inode_operations reiserfs_symlink_inode_operations = { | |||
1564 | /* | 1564 | /* |
1565 | * special file operations.. just xattr/acl stuff | 1565 | * special file operations.. just xattr/acl stuff |
1566 | */ | 1566 | */ |
1567 | struct inode_operations reiserfs_special_inode_operations = { | 1567 | const struct inode_operations reiserfs_special_inode_operations = { |
1568 | .setattr = reiserfs_setattr, | 1568 | .setattr = reiserfs_setattr, |
1569 | .setxattr = reiserfs_setxattr, | 1569 | .setxattr = reiserfs_setxattr, |
1570 | .getxattr = reiserfs_getxattr, | 1570 | .getxattr = reiserfs_getxattr, |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 58ad4551a7c1..f13a7f164dc6 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -593,7 +593,7 @@ static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t, | |||
593 | loff_t); | 593 | loff_t); |
594 | #endif | 594 | #endif |
595 | 595 | ||
596 | static struct super_operations reiserfs_sops = { | 596 | static const struct super_operations reiserfs_sops = { |
597 | .alloc_inode = reiserfs_alloc_inode, | 597 | .alloc_inode = reiserfs_alloc_inode, |
598 | .destroy_inode = reiserfs_destroy_inode, | 598 | .destroy_inode = reiserfs_destroy_inode, |
599 | .write_inode = reiserfs_write_inode, | 599 | .write_inode = reiserfs_write_inode, |
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index d3e243a6f609..fd601014813e 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c | |||
@@ -110,7 +110,7 @@ romfs_checksum(void *data, int size) | |||
110 | return sum; | 110 | return sum; |
111 | } | 111 | } |
112 | 112 | ||
113 | static struct super_operations romfs_ops; | 113 | static const struct super_operations romfs_ops; |
114 | 114 | ||
115 | static int romfs_fill_super(struct super_block *s, void *data, int silent) | 115 | static int romfs_fill_super(struct super_block *s, void *data, int silent) |
116 | { | 116 | { |
@@ -468,7 +468,7 @@ static const struct file_operations romfs_dir_operations = { | |||
468 | .readdir = romfs_readdir, | 468 | .readdir = romfs_readdir, |
469 | }; | 469 | }; |
470 | 470 | ||
471 | static struct inode_operations romfs_dir_inode_operations = { | 471 | static const struct inode_operations romfs_dir_inode_operations = { |
472 | .lookup = romfs_lookup, | 472 | .lookup = romfs_lookup, |
473 | }; | 473 | }; |
474 | 474 | ||
@@ -598,7 +598,7 @@ static int romfs_remount(struct super_block *sb, int *flags, char *data) | |||
598 | return 0; | 598 | return 0; |
599 | } | 599 | } |
600 | 600 | ||
601 | static struct super_operations romfs_ops = { | 601 | static const struct super_operations romfs_ops = { |
602 | .alloc_inode = romfs_alloc_inode, | 602 | .alloc_inode = romfs_alloc_inode, |
603 | .destroy_inode = romfs_destroy_inode, | 603 | .destroy_inode = romfs_destroy_inode, |
604 | .read_inode = romfs_read_inode, | 604 | .read_inode = romfs_read_inode, |
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index b1e58d1ac9ca..50136b1a3eca 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c | |||
@@ -42,7 +42,7 @@ const struct file_operations smb_dir_operations = | |||
42 | .open = smb_dir_open, | 42 | .open = smb_dir_open, |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct inode_operations smb_dir_inode_operations = | 45 | const struct inode_operations smb_dir_inode_operations = |
46 | { | 46 | { |
47 | .create = smb_create, | 47 | .create = smb_create, |
48 | .lookup = smb_lookup, | 48 | .lookup = smb_lookup, |
@@ -54,7 +54,7 @@ struct inode_operations smb_dir_inode_operations = | |||
54 | .setattr = smb_notify_change, | 54 | .setattr = smb_notify_change, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | struct inode_operations smb_dir_inode_operations_unix = | 57 | const struct inode_operations smb_dir_inode_operations_unix = |
58 | { | 58 | { |
59 | .create = smb_create, | 59 | .create = smb_create, |
60 | .lookup = smb_lookup, | 60 | .lookup = smb_lookup, |
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index e50533a79517..f161797160c4 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c | |||
@@ -418,7 +418,7 @@ const struct file_operations smb_file_operations = | |||
418 | .sendfile = smb_file_sendfile, | 418 | .sendfile = smb_file_sendfile, |
419 | }; | 419 | }; |
420 | 420 | ||
421 | struct inode_operations smb_file_inode_operations = | 421 | const struct inode_operations smb_file_inode_operations = |
422 | { | 422 | { |
423 | .permission = smb_file_permission, | 423 | .permission = smb_file_permission, |
424 | .getattr = smb_getattr, | 424 | .getattr = smb_getattr, |
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 84dfe3f3482e..5faba4f1c9ab 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c | |||
@@ -98,7 +98,7 @@ static int smb_remount(struct super_block *sb, int *flags, char *data) | |||
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | static struct super_operations smb_sops = | 101 | static const struct super_operations smb_sops = |
102 | { | 102 | { |
103 | .alloc_inode = smb_alloc_inode, | 103 | .alloc_inode = smb_alloc_inode, |
104 | .destroy_inode = smb_destroy_inode, | 104 | .destroy_inode = smb_destroy_inode, |
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h index 34fb462b2379..03f456c1b7d4 100644 --- a/fs/smbfs/proto.h +++ b/fs/smbfs/proto.h | |||
@@ -36,8 +36,8 @@ extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, stru | |||
36 | extern void smb_install_null_ops(struct smb_ops *ops); | 36 | extern void smb_install_null_ops(struct smb_ops *ops); |
37 | /* dir.c */ | 37 | /* dir.c */ |
38 | extern const struct file_operations smb_dir_operations; | 38 | extern const struct file_operations smb_dir_operations; |
39 | extern struct inode_operations smb_dir_inode_operations; | 39 | extern const struct inode_operations smb_dir_inode_operations; |
40 | extern struct inode_operations smb_dir_inode_operations_unix; | 40 | extern const struct inode_operations smb_dir_inode_operations_unix; |
41 | extern void smb_new_dentry(struct dentry *dentry); | 41 | extern void smb_new_dentry(struct dentry *dentry); |
42 | extern void smb_renew_times(struct dentry *dentry); | 42 | extern void smb_renew_times(struct dentry *dentry); |
43 | /* cache.c */ | 43 | /* cache.c */ |
@@ -65,7 +65,7 @@ extern int smb_notify_change(struct dentry *dentry, struct iattr *attr); | |||
65 | /* file.c */ | 65 | /* file.c */ |
66 | extern const struct address_space_operations smb_file_aops; | 66 | extern const struct address_space_operations smb_file_aops; |
67 | extern const struct file_operations smb_file_operations; | 67 | extern const struct file_operations smb_file_operations; |
68 | extern struct inode_operations smb_file_inode_operations; | 68 | extern const struct inode_operations smb_file_inode_operations; |
69 | /* ioctl.c */ | 69 | /* ioctl.c */ |
70 | extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); | 70 | extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); |
71 | /* smbiod.c */ | 71 | /* smbiod.c */ |
@@ -84,4 +84,4 @@ extern int smb_request_send_server(struct smb_sb_info *server); | |||
84 | extern int smb_request_recv(struct smb_sb_info *server); | 84 | extern int smb_request_recv(struct smb_sb_info *server); |
85 | /* symlink.c */ | 85 | /* symlink.c */ |
86 | extern int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname); | 86 | extern int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname); |
87 | extern struct inode_operations smb_link_inode_operations; | 87 | extern const struct inode_operations smb_link_inode_operations; |
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c index a4bcae8a9aff..42261dbdf60f 100644 --- a/fs/smbfs/request.c +++ b/fs/smbfs/request.c | |||
@@ -61,7 +61,7 @@ static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server, | |||
61 | struct smb_request *req; | 61 | struct smb_request *req; |
62 | unsigned char *buf = NULL; | 62 | unsigned char *buf = NULL; |
63 | 63 | ||
64 | req = kmem_cache_alloc(req_cachep, GFP_KERNEL); | 64 | req = kmem_cache_zalloc(req_cachep, GFP_KERNEL); |
65 | VERBOSE("allocating request: %p\n", req); | 65 | VERBOSE("allocating request: %p\n", req); |
66 | if (!req) | 66 | if (!req) |
67 | goto out; | 67 | goto out; |
@@ -74,7 +74,6 @@ static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server, | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | memset(req, 0, sizeof(struct smb_request)); | ||
78 | req->rq_buffer = buf; | 77 | req->rq_buffer = buf; |
79 | req->rq_bufsize = bufsize; | 78 | req->rq_bufsize = bufsize; |
80 | req->rq_server = server; | 79 | req->rq_server = server; |
diff --git a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c index cdc53c4fb381..fea20ceb8a5f 100644 --- a/fs/smbfs/symlink.c +++ b/fs/smbfs/symlink.c | |||
@@ -6,7 +6,6 @@ | |||
6 | * Please add a note about your changes to smbfs in the ChangeLog file. | 6 | * Please add a note about your changes to smbfs in the ChangeLog file. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
11 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
12 | #include <linux/fcntl.h> | 11 | #include <linux/fcntl.h> |
@@ -62,7 +61,7 @@ static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p) | |||
62 | __putname(s); | 61 | __putname(s); |
63 | } | 62 | } |
64 | 63 | ||
65 | struct inode_operations smb_link_inode_operations = | 64 | const struct inode_operations smb_link_inode_operations = |
66 | { | 65 | { |
67 | .readlink = generic_readlink, | 66 | .readlink = generic_readlink, |
68 | .follow_link = smb_follow_link, | 67 | .follow_link = smb_follow_link, |
diff --git a/fs/stack.c b/fs/stack.c index 8ffb880d2f46..67716f6a1a4a 100644 --- a/fs/stack.c +++ b/fs/stack.c | |||
@@ -20,11 +20,6 @@ EXPORT_SYMBOL_GPL(fsstack_copy_inode_size); | |||
20 | void fsstack_copy_attr_all(struct inode *dest, const struct inode *src, | 20 | void fsstack_copy_attr_all(struct inode *dest, const struct inode *src, |
21 | int (*get_nlinks)(struct inode *)) | 21 | int (*get_nlinks)(struct inode *)) |
22 | { | 22 | { |
23 | if (!get_nlinks) | ||
24 | dest->i_nlink = src->i_nlink; | ||
25 | else | ||
26 | dest->i_nlink = (*get_nlinks)(dest); | ||
27 | |||
28 | dest->i_mode = src->i_mode; | 23 | dest->i_mode = src->i_mode; |
29 | dest->i_uid = src->i_uid; | 24 | dest->i_uid = src->i_uid; |
30 | dest->i_gid = src->i_gid; | 25 | dest->i_gid = src->i_gid; |
@@ -34,5 +29,14 @@ void fsstack_copy_attr_all(struct inode *dest, const struct inode *src, | |||
34 | dest->i_ctime = src->i_ctime; | 29 | dest->i_ctime = src->i_ctime; |
35 | dest->i_blkbits = src->i_blkbits; | 30 | dest->i_blkbits = src->i_blkbits; |
36 | dest->i_flags = src->i_flags; | 31 | dest->i_flags = src->i_flags; |
32 | |||
33 | /* | ||
34 | * Update the nlinks AFTER updating the above fields, because the | ||
35 | * get_links callback may depend on them. | ||
36 | */ | ||
37 | if (!get_nlinks) | ||
38 | dest->i_nlink = src->i_nlink; | ||
39 | else | ||
40 | dest->i_nlink = (*get_nlinks)(dest); | ||
37 | } | 41 | } |
38 | EXPORT_SYMBOL_GPL(fsstack_copy_attr_all); | 42 | EXPORT_SYMBOL_GPL(fsstack_copy_attr_all); |
diff --git a/fs/super.c b/fs/super.c index 3e7458c2bb76..60b1e50cbf53 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -285,7 +285,7 @@ int fsync_super(struct super_block *sb) | |||
285 | */ | 285 | */ |
286 | void generic_shutdown_super(struct super_block *sb) | 286 | void generic_shutdown_super(struct super_block *sb) |
287 | { | 287 | { |
288 | struct super_operations *sop = sb->s_op; | 288 | const struct super_operations *sop = sb->s_op; |
289 | 289 | ||
290 | if (sb->s_root) { | 290 | if (sb->s_root) { |
291 | shrink_dcache_for_umount(sb); | 291 | shrink_dcache_for_umount(sb); |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 9dcdf556c99c..8813990304fe 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -37,11 +37,10 @@ static struct sysfs_dirent * __sysfs_new_dirent(void * element) | |||
37 | { | 37 | { |
38 | struct sysfs_dirent * sd; | 38 | struct sysfs_dirent * sd; |
39 | 39 | ||
40 | sd = kmem_cache_alloc(sysfs_dir_cachep, GFP_KERNEL); | 40 | sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); |
41 | if (!sd) | 41 | if (!sd) |
42 | return NULL; | 42 | return NULL; |
43 | 43 | ||
44 | memset(sd, 0, sizeof(*sd)); | ||
45 | atomic_set(&sd->s_count, 1); | 44 | atomic_set(&sd->s_count, 1); |
46 | atomic_set(&sd->s_event, 1); | 45 | atomic_set(&sd->s_event, 1); |
47 | INIT_LIST_HEAD(&sd->s_children); | 46 | INIT_LIST_HEAD(&sd->s_children); |
@@ -297,7 +296,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
297 | return ERR_PTR(err); | 296 | return ERR_PTR(err); |
298 | } | 297 | } |
299 | 298 | ||
300 | struct inode_operations sysfs_dir_inode_operations = { | 299 | const struct inode_operations sysfs_dir_inode_operations = { |
301 | .lookup = sysfs_lookup, | 300 | .lookup = sysfs_lookup, |
302 | .setattr = sysfs_setattr, | 301 | .setattr = sysfs_setattr, |
303 | }; | 302 | }; |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index c0e117649a4d..8d4d839a9d88 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -54,7 +54,7 @@ static struct sysfs_ops subsys_sysfs_ops = { | |||
54 | /** | 54 | /** |
55 | * add_to_collection - add buffer to a collection | 55 | * add_to_collection - add buffer to a collection |
56 | * @buffer: buffer to be added | 56 | * @buffer: buffer to be added |
57 | * @node inode of set to add to | 57 | * @node: inode of set to add to |
58 | */ | 58 | */ |
59 | 59 | ||
60 | static inline void | 60 | static inline void |
@@ -502,6 +502,30 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) | |||
502 | 502 | ||
503 | 503 | ||
504 | /** | 504 | /** |
505 | * sysfs_add_file_to_group - add an attribute file to a pre-existing group. | ||
506 | * @kobj: object we're acting for. | ||
507 | * @attr: attribute descriptor. | ||
508 | * @group: group name. | ||
509 | */ | ||
510 | int sysfs_add_file_to_group(struct kobject *kobj, | ||
511 | const struct attribute *attr, const char *group) | ||
512 | { | ||
513 | struct dentry *dir; | ||
514 | int error; | ||
515 | |||
516 | dir = lookup_one_len(group, kobj->dentry, strlen(group)); | ||
517 | if (IS_ERR(dir)) | ||
518 | error = PTR_ERR(dir); | ||
519 | else { | ||
520 | error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR); | ||
521 | dput(dir); | ||
522 | } | ||
523 | return error; | ||
524 | } | ||
525 | EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); | ||
526 | |||
527 | |||
528 | /** | ||
505 | * sysfs_update_file - update the modified timestamp on an object attribute. | 529 | * sysfs_update_file - update the modified timestamp on an object attribute. |
506 | * @kobj: object we're acting for. | 530 | * @kobj: object we're acting for. |
507 | * @attr: attribute descriptor. | 531 | * @attr: attribute descriptor. |
@@ -586,6 +610,26 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) | |||
586 | } | 610 | } |
587 | 611 | ||
588 | 612 | ||
613 | /** | ||
614 | * sysfs_remove_file_from_group - remove an attribute file from a group. | ||
615 | * @kobj: object we're acting for. | ||
616 | * @attr: attribute descriptor. | ||
617 | * @group: group name. | ||
618 | */ | ||
619 | void sysfs_remove_file_from_group(struct kobject *kobj, | ||
620 | const struct attribute *attr, const char *group) | ||
621 | { | ||
622 | struct dentry *dir; | ||
623 | |||
624 | dir = lookup_one_len(group, kobj->dentry, strlen(group)); | ||
625 | if (!IS_ERR(dir)) { | ||
626 | sysfs_hash_and_remove(dir, attr->name); | ||
627 | dput(dir); | ||
628 | } | ||
629 | } | ||
630 | EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); | ||
631 | |||
632 | |||
589 | EXPORT_SYMBOL_GPL(sysfs_create_file); | 633 | EXPORT_SYMBOL_GPL(sysfs_create_file); |
590 | EXPORT_SYMBOL_GPL(sysfs_remove_file); | 634 | EXPORT_SYMBOL_GPL(sysfs_remove_file); |
591 | EXPORT_SYMBOL_GPL(sysfs_update_file); | 635 | EXPORT_SYMBOL_GPL(sysfs_update_file); |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 542d2bcc73df..dd1344b007f5 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -29,7 +29,7 @@ static struct backing_dev_info sysfs_backing_dev_info = { | |||
29 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, | 29 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, |
30 | }; | 30 | }; |
31 | 31 | ||
32 | static struct inode_operations sysfs_inode_operations ={ | 32 | static const struct inode_operations sysfs_inode_operations ={ |
33 | .setattr = sysfs_setattr, | 33 | .setattr = sysfs_setattr, |
34 | }; | 34 | }; |
35 | 35 | ||
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index f6a87a824883..23a48a38e6af 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -21,7 +21,7 @@ struct kmem_cache *sysfs_dir_cachep; | |||
21 | 21 | ||
22 | static void sysfs_clear_inode(struct inode *inode); | 22 | static void sysfs_clear_inode(struct inode *inode); |
23 | 23 | ||
24 | static struct super_operations sysfs_ops = { | 24 | static const struct super_operations sysfs_ops = { |
25 | .statfs = simple_statfs, | 25 | .statfs = simple_statfs, |
26 | .drop_inode = sysfs_delete_inode, | 26 | .drop_inode = sysfs_delete_inode, |
27 | .clear_inode = sysfs_clear_inode, | 27 | .clear_inode = sysfs_clear_inode, |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 4869f611192f..7b9c5bfde920 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -181,7 +181,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co | |||
181 | free_page((unsigned long)page); | 181 | free_page((unsigned long)page); |
182 | } | 182 | } |
183 | 183 | ||
184 | struct inode_operations sysfs_symlink_inode_operations = { | 184 | const struct inode_operations sysfs_symlink_inode_operations = { |
185 | .readlink = generic_readlink, | 185 | .readlink = generic_readlink, |
186 | .follow_link = sysfs_follow_link, | 186 | .follow_link = sysfs_follow_link, |
187 | .put_link = sysfs_put_link, | 187 | .put_link = sysfs_put_link, |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index fe1cbfd208ed..a77c57e5a6d5 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -1,3 +1,14 @@ | |||
1 | struct sysfs_dirent { | ||
2 | atomic_t s_count; | ||
3 | struct list_head s_sibling; | ||
4 | struct list_head s_children; | ||
5 | void * s_element; | ||
6 | int s_type; | ||
7 | umode_t s_mode; | ||
8 | struct dentry * s_dentry; | ||
9 | struct iattr * s_iattr; | ||
10 | atomic_t s_event; | ||
11 | }; | ||
1 | 12 | ||
2 | extern struct vfsmount * sysfs_mount; | 13 | extern struct vfsmount * sysfs_mount; |
3 | extern struct kmem_cache *sysfs_dir_cachep; | 14 | extern struct kmem_cache *sysfs_dir_cachep; |
@@ -26,8 +37,8 @@ extern struct super_block * sysfs_sb; | |||
26 | extern const struct file_operations sysfs_dir_operations; | 37 | extern const struct file_operations sysfs_dir_operations; |
27 | extern const struct file_operations sysfs_file_operations; | 38 | extern const struct file_operations sysfs_file_operations; |
28 | extern const struct file_operations bin_fops; | 39 | extern const struct file_operations bin_fops; |
29 | extern struct inode_operations sysfs_dir_inode_operations; | 40 | extern const struct inode_operations sysfs_dir_inode_operations; |
30 | extern struct inode_operations sysfs_symlink_inode_operations; | 41 | extern const struct inode_operations sysfs_symlink_inode_operations; |
31 | 42 | ||
32 | struct sysfs_symlink { | 43 | struct sysfs_symlink { |
33 | char * link_name; | 44 | char * link_name; |
diff --git a/fs/sysv/file.c b/fs/sysv/file.c index 47a4b728f15b..0732ddb9020b 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c | |||
@@ -30,7 +30,7 @@ const struct file_operations sysv_file_operations = { | |||
30 | .sendfile = generic_file_sendfile, | 30 | .sendfile = generic_file_sendfile, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | struct inode_operations sysv_file_inode_operations = { | 33 | const struct inode_operations sysv_file_inode_operations = { |
34 | .truncate = sysv_truncate, | 34 | .truncate = sysv_truncate, |
35 | .getattr = sysv_getattr, | 35 | .getattr = sysv_getattr, |
36 | }; | 36 | }; |
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index ead9864567e3..9311cac186fe 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
@@ -142,7 +142,7 @@ static inline void write3byte(struct sysv_sb_info *sbi, | |||
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | ||
145 | static struct inode_operations sysv_symlink_inode_operations = { | 145 | static const struct inode_operations sysv_symlink_inode_operations = { |
146 | .readlink = generic_readlink, | 146 | .readlink = generic_readlink, |
147 | .follow_link = page_follow_link_light, | 147 | .follow_link = page_follow_link_light, |
148 | .put_link = page_put_link, | 148 | .put_link = page_put_link, |
@@ -327,7 +327,7 @@ static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags) | |||
327 | inode_init_once(&si->vfs_inode); | 327 | inode_init_once(&si->vfs_inode); |
328 | } | 328 | } |
329 | 329 | ||
330 | struct super_operations sysv_sops = { | 330 | const struct super_operations sysv_sops = { |
331 | .alloc_inode = sysv_alloc_inode, | 331 | .alloc_inode = sysv_alloc_inode, |
332 | .destroy_inode = sysv_destroy_inode, | 332 | .destroy_inode = sysv_destroy_inode, |
333 | .read_inode = sysv_read_inode, | 333 | .read_inode = sysv_read_inode, |
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index f7c08db8e34c..4e48abbd2b5d 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c | |||
@@ -292,7 +292,7 @@ out: | |||
292 | /* | 292 | /* |
293 | * directories can handle most operations... | 293 | * directories can handle most operations... |
294 | */ | 294 | */ |
295 | struct inode_operations sysv_dir_inode_operations = { | 295 | const struct inode_operations sysv_dir_inode_operations = { |
296 | .create = sysv_create, | 296 | .create = sysv_create, |
297 | .lookup = sysv_lookup, | 297 | .lookup = sysv_lookup, |
298 | .link = sysv_link, | 298 | .link = sysv_link, |
diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c index b85ce61d635c..00d2f8a43e4e 100644 --- a/fs/sysv/symlink.c +++ b/fs/sysv/symlink.c | |||
@@ -14,7 +14,7 @@ static void *sysv_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
14 | return NULL; | 14 | return NULL; |
15 | } | 15 | } |
16 | 16 | ||
17 | struct inode_operations sysv_fast_symlink_inode_operations = { | 17 | const struct inode_operations sysv_fast_symlink_inode_operations = { |
18 | .readlink = generic_readlink, | 18 | .readlink = generic_readlink, |
19 | .follow_link = sysv_follow_link, | 19 | .follow_link = sysv_follow_link, |
20 | }; | 20 | }; |
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index dcb18b2171fe..5b4fedf17cc4 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h | |||
@@ -159,13 +159,13 @@ extern struct sysv_dir_entry *sysv_dotdot(struct inode *, struct page **); | |||
159 | extern ino_t sysv_inode_by_name(struct dentry *); | 159 | extern ino_t sysv_inode_by_name(struct dentry *); |
160 | 160 | ||
161 | 161 | ||
162 | extern struct inode_operations sysv_file_inode_operations; | 162 | extern const struct inode_operations sysv_file_inode_operations; |
163 | extern struct inode_operations sysv_dir_inode_operations; | 163 | extern const struct inode_operations sysv_dir_inode_operations; |
164 | extern struct inode_operations sysv_fast_symlink_inode_operations; | 164 | extern const struct inode_operations sysv_fast_symlink_inode_operations; |
165 | extern const struct file_operations sysv_file_operations; | 165 | extern const struct file_operations sysv_file_operations; |
166 | extern const struct file_operations sysv_dir_operations; | 166 | extern const struct file_operations sysv_dir_operations; |
167 | extern const struct address_space_operations sysv_aops; | 167 | extern const struct address_space_operations sysv_aops; |
168 | extern struct super_operations sysv_sops; | 168 | extern const struct super_operations sysv_sops; |
169 | extern struct dentry_operations sysv_dentry_operations; | 169 | extern struct dentry_operations sysv_dentry_operations; |
170 | 170 | ||
171 | 171 | ||
diff --git a/fs/udf/file.c b/fs/udf/file.c index d81f2db7b0e3..40d5047defea 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -263,6 +263,6 @@ const struct file_operations udf_file_operations = { | |||
263 | .sendfile = generic_file_sendfile, | 263 | .sendfile = generic_file_sendfile, |
264 | }; | 264 | }; |
265 | 265 | ||
266 | struct inode_operations udf_file_inode_operations = { | 266 | const struct inode_operations udf_file_inode_operations = { |
267 | .truncate = udf_truncate, | 267 | .truncate = udf_truncate, |
268 | }; | 268 | }; |
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 73163325e5ec..fe361cd19a98 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -1308,7 +1308,7 @@ end_rename: | |||
1308 | return retval; | 1308 | return retval; |
1309 | } | 1309 | } |
1310 | 1310 | ||
1311 | struct inode_operations udf_dir_inode_operations = { | 1311 | const struct inode_operations udf_dir_inode_operations = { |
1312 | .lookup = udf_lookup, | 1312 | .lookup = udf_lookup, |
1313 | .create = udf_create, | 1313 | .create = udf_create, |
1314 | .link = udf_link, | 1314 | .link = udf_link, |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 1dbc2955f02e..8672b88f7ff2 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -160,7 +160,7 @@ static void destroy_inodecache(void) | |||
160 | } | 160 | } |
161 | 161 | ||
162 | /* Superblock operations */ | 162 | /* Superblock operations */ |
163 | static struct super_operations udf_sb_ops = { | 163 | static const struct super_operations udf_sb_ops = { |
164 | .alloc_inode = udf_alloc_inode, | 164 | .alloc_inode = udf_alloc_inode, |
165 | .destroy_inode = udf_destroy_inode, | 165 | .destroy_inode = udf_destroy_inode, |
166 | .write_inode = udf_write_inode, | 166 | .write_inode = udf_write_inode, |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 1033b7cf2939..ee1dece1f6f5 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
@@ -42,9 +42,9 @@ struct task_struct; | |||
42 | struct buffer_head; | 42 | struct buffer_head; |
43 | struct super_block; | 43 | struct super_block; |
44 | 44 | ||
45 | extern struct inode_operations udf_dir_inode_operations; | 45 | extern const struct inode_operations udf_dir_inode_operations; |
46 | extern const struct file_operations udf_dir_operations; | 46 | extern const struct file_operations udf_dir_operations; |
47 | extern struct inode_operations udf_file_inode_operations; | 47 | extern const struct inode_operations udf_file_inode_operations; |
48 | extern const struct file_operations udf_file_operations; | 48 | extern const struct file_operations udf_file_operations; |
49 | extern const struct address_space_operations udf_aops; | 49 | extern const struct address_space_operations udf_aops; |
50 | extern const struct address_space_operations udf_adinicb_aops; | 50 | extern const struct address_space_operations udf_adinicb_aops; |
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 638f4c585e89..bcc44084e004 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * Copyright (C) 1998 | 4 | * Copyright (C) 1998 |
5 | * Daniel Pirkl <daniel.pirkl@email.cz> | 5 | * Daniel Pirkl <daniel.pirkl@email.cz> |
6 | * Charles University, Faculty of Mathematics and Physics | 6 | * Charles University, Faculty of Mathematics and Physics |
7 | * | ||
8 | * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007 | ||
7 | */ | 9 | */ |
8 | 10 | ||
9 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
@@ -14,45 +16,48 @@ | |||
14 | #include <linux/quotaops.h> | 16 | #include <linux/quotaops.h> |
15 | #include <linux/buffer_head.h> | 17 | #include <linux/buffer_head.h> |
16 | #include <linux/capability.h> | 18 | #include <linux/capability.h> |
17 | #include <linux/sched.h> | ||
18 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
19 | #include <asm/byteorder.h> | 20 | #include <asm/byteorder.h> |
20 | 21 | ||
21 | #include "swab.h" | 22 | #include "swab.h" |
22 | #include "util.h" | 23 | #include "util.h" |
23 | 24 | ||
24 | static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *); | 25 | #define INVBLOCK ((u64)-1L) |
25 | static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *); | 26 | |
26 | static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *); | 27 | static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned, int *); |
27 | static unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned); | 28 | static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *); |
29 | static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *); | ||
30 | static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned); | ||
28 | static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[]; | 31 | static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[]; |
29 | static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int); | 32 | static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int); |
30 | 33 | ||
31 | /* | 34 | /* |
32 | * Free 'count' fragments from fragment number 'fragment' | 35 | * Free 'count' fragments from fragment number 'fragment' |
33 | */ | 36 | */ |
34 | void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count) | 37 | void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) |
35 | { | 38 | { |
36 | struct super_block * sb; | 39 | struct super_block * sb; |
37 | struct ufs_sb_private_info * uspi; | 40 | struct ufs_sb_private_info * uspi; |
38 | struct ufs_super_block_first * usb1; | 41 | struct ufs_super_block_first * usb1; |
39 | struct ufs_cg_private_info * ucpi; | 42 | struct ufs_cg_private_info * ucpi; |
40 | struct ufs_cylinder_group * ucg; | 43 | struct ufs_cylinder_group * ucg; |
41 | unsigned cgno, bit, end_bit, bbase, blkmap, i, blkno, cylno; | 44 | unsigned cgno, bit, end_bit, bbase, blkmap, i; |
45 | u64 blkno; | ||
42 | 46 | ||
43 | sb = inode->i_sb; | 47 | sb = inode->i_sb; |
44 | uspi = UFS_SB(sb)->s_uspi; | 48 | uspi = UFS_SB(sb)->s_uspi; |
45 | usb1 = ubh_get_usb_first(uspi); | 49 | usb1 = ubh_get_usb_first(uspi); |
46 | 50 | ||
47 | UFSD("ENTER, fragment %u, count %u\n", fragment, count); | 51 | UFSD("ENTER, fragment %llu, count %u\n", |
52 | (unsigned long long)fragment, count); | ||
48 | 53 | ||
49 | if (ufs_fragnum(fragment) + count > uspi->s_fpg) | 54 | if (ufs_fragnum(fragment) + count > uspi->s_fpg) |
50 | ufs_error (sb, "ufs_free_fragments", "internal error"); | 55 | ufs_error (sb, "ufs_free_fragments", "internal error"); |
51 | 56 | ||
52 | lock_super(sb); | 57 | lock_super(sb); |
53 | 58 | ||
54 | cgno = ufs_dtog(fragment); | 59 | cgno = ufs_dtog(uspi, fragment); |
55 | bit = ufs_dtogd(fragment); | 60 | bit = ufs_dtogd(uspi, fragment); |
56 | if (cgno >= uspi->s_ncg) { | 61 | if (cgno >= uspi->s_ncg) { |
57 | ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device"); | 62 | ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device"); |
58 | goto failed; | 63 | goto failed; |
@@ -101,9 +106,13 @@ void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count) | |||
101 | fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); | 106 | fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); |
102 | uspi->cs_total.cs_nbfree++; | 107 | uspi->cs_total.cs_nbfree++; |
103 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); | 108 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); |
104 | cylno = ufs_cbtocylno (bbase); | 109 | if (uspi->fs_magic != UFS2_MAGIC) { |
105 | fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1); | 110 | unsigned cylno = ufs_cbtocylno (bbase); |
106 | fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); | 111 | |
112 | fs16_add(sb, &ubh_cg_blks(ucpi, cylno, | ||
113 | ufs_cbtorpos(bbase)), 1); | ||
114 | fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); | ||
115 | } | ||
107 | } | 116 | } |
108 | 117 | ||
109 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 118 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
@@ -127,24 +136,27 @@ failed: | |||
127 | /* | 136 | /* |
128 | * Free 'count' fragments from fragment number 'fragment' (free whole blocks) | 137 | * Free 'count' fragments from fragment number 'fragment' (free whole blocks) |
129 | */ | 138 | */ |
130 | void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count) | 139 | void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) |
131 | { | 140 | { |
132 | struct super_block * sb; | 141 | struct super_block * sb; |
133 | struct ufs_sb_private_info * uspi; | 142 | struct ufs_sb_private_info * uspi; |
134 | struct ufs_super_block_first * usb1; | 143 | struct ufs_super_block_first * usb1; |
135 | struct ufs_cg_private_info * ucpi; | 144 | struct ufs_cg_private_info * ucpi; |
136 | struct ufs_cylinder_group * ucg; | 145 | struct ufs_cylinder_group * ucg; |
137 | unsigned overflow, cgno, bit, end_bit, blkno, i, cylno; | 146 | unsigned overflow, cgno, bit, end_bit, i; |
147 | u64 blkno; | ||
138 | 148 | ||
139 | sb = inode->i_sb; | 149 | sb = inode->i_sb; |
140 | uspi = UFS_SB(sb)->s_uspi; | 150 | uspi = UFS_SB(sb)->s_uspi; |
141 | usb1 = ubh_get_usb_first(uspi); | 151 | usb1 = ubh_get_usb_first(uspi); |
142 | 152 | ||
143 | UFSD("ENTER, fragment %u, count %u\n", fragment, count); | 153 | UFSD("ENTER, fragment %llu, count %u\n", |
154 | (unsigned long long)fragment, count); | ||
144 | 155 | ||
145 | if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) { | 156 | if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) { |
146 | ufs_error (sb, "ufs_free_blocks", "internal error, " | 157 | ufs_error (sb, "ufs_free_blocks", "internal error, " |
147 | "fragment %u, count %u\n", fragment, count); | 158 | "fragment %llu, count %u\n", |
159 | (unsigned long long)fragment, count); | ||
148 | goto failed; | 160 | goto failed; |
149 | } | 161 | } |
150 | 162 | ||
@@ -152,8 +164,8 @@ void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count) | |||
152 | 164 | ||
153 | do_more: | 165 | do_more: |
154 | overflow = 0; | 166 | overflow = 0; |
155 | cgno = ufs_dtog (fragment); | 167 | cgno = ufs_dtog(uspi, fragment); |
156 | bit = ufs_dtogd (fragment); | 168 | bit = ufs_dtogd(uspi, fragment); |
157 | if (cgno >= uspi->s_ncg) { | 169 | if (cgno >= uspi->s_ncg) { |
158 | ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device"); | 170 | ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device"); |
159 | goto failed_unlock; | 171 | goto failed_unlock; |
@@ -187,9 +199,14 @@ do_more: | |||
187 | fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); | 199 | fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); |
188 | uspi->cs_total.cs_nbfree++; | 200 | uspi->cs_total.cs_nbfree++; |
189 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); | 201 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); |
190 | cylno = ufs_cbtocylno(i); | 202 | |
191 | fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1); | 203 | if (uspi->fs_magic != UFS2_MAGIC) { |
192 | fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); | 204 | unsigned cylno = ufs_cbtocylno(i); |
205 | |||
206 | fs16_add(sb, &ubh_cg_blks(ucpi, cylno, | ||
207 | ufs_cbtorpos(i)), 1); | ||
208 | fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); | ||
209 | } | ||
193 | } | 210 | } |
194 | 211 | ||
195 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 212 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
@@ -308,15 +325,19 @@ static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n, | |||
308 | } | 325 | } |
309 | } | 326 | } |
310 | 327 | ||
311 | unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, | 328 | u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, |
312 | unsigned goal, unsigned count, int * err, struct page *locked_page) | 329 | u64 goal, unsigned count, int *err, |
330 | struct page *locked_page) | ||
313 | { | 331 | { |
314 | struct super_block * sb; | 332 | struct super_block * sb; |
315 | struct ufs_sb_private_info * uspi; | 333 | struct ufs_sb_private_info * uspi; |
316 | struct ufs_super_block_first * usb1; | 334 | struct ufs_super_block_first * usb1; |
317 | unsigned cgno, oldcount, newcount, tmp, request, result; | 335 | unsigned cgno, oldcount, newcount; |
336 | u64 tmp, request, result; | ||
318 | 337 | ||
319 | UFSD("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count); | 338 | UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n", |
339 | inode->i_ino, (unsigned long long)fragment, | ||
340 | (unsigned long long)goal, count); | ||
320 | 341 | ||
321 | sb = inode->i_sb; | 342 | sb = inode->i_sb; |
322 | uspi = UFS_SB(sb)->s_uspi; | 343 | uspi = UFS_SB(sb)->s_uspi; |
@@ -324,11 +345,12 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, | |||
324 | *err = -ENOSPC; | 345 | *err = -ENOSPC; |
325 | 346 | ||
326 | lock_super (sb); | 347 | lock_super (sb); |
327 | 348 | tmp = ufs_data_ptr_to_cpu(sb, p); | |
328 | tmp = fs32_to_cpu(sb, *p); | 349 | |
329 | if (count + ufs_fragnum(fragment) > uspi->s_fpb) { | 350 | if (count + ufs_fragnum(fragment) > uspi->s_fpb) { |
330 | ufs_warning (sb, "ufs_new_fragments", "internal warning" | 351 | ufs_warning(sb, "ufs_new_fragments", "internal warning" |
331 | " fragment %u, count %u", fragment, count); | 352 | " fragment %llu, count %u", |
353 | (unsigned long long)fragment, count); | ||
332 | count = uspi->s_fpb - ufs_fragnum(fragment); | 354 | count = uspi->s_fpb - ufs_fragnum(fragment); |
333 | } | 355 | } |
334 | oldcount = ufs_fragnum (fragment); | 356 | oldcount = ufs_fragnum (fragment); |
@@ -339,10 +361,12 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, | |||
339 | */ | 361 | */ |
340 | if (oldcount) { | 362 | if (oldcount) { |
341 | if (!tmp) { | 363 | if (!tmp) { |
342 | ufs_error (sb, "ufs_new_fragments", "internal error, " | 364 | ufs_error(sb, "ufs_new_fragments", "internal error, " |
343 | "fragment %u, tmp %u\n", fragment, tmp); | 365 | "fragment %llu, tmp %llu\n", |
344 | unlock_super (sb); | 366 | (unsigned long long)fragment, |
345 | return (unsigned)-1; | 367 | (unsigned long long)tmp); |
368 | unlock_super(sb); | ||
369 | return INVBLOCK; | ||
346 | } | 370 | } |
347 | if (fragment < UFS_I(inode)->i_lastfrag) { | 371 | if (fragment < UFS_I(inode)->i_lastfrag) { |
348 | UFSD("EXIT (ALREADY ALLOCATED)\n"); | 372 | UFSD("EXIT (ALREADY ALLOCATED)\n"); |
@@ -372,7 +396,7 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, | |||
372 | if (goal == 0) | 396 | if (goal == 0) |
373 | cgno = ufs_inotocg (inode->i_ino); | 397 | cgno = ufs_inotocg (inode->i_ino); |
374 | else | 398 | else |
375 | cgno = ufs_dtog (goal); | 399 | cgno = ufs_dtog(uspi, goal); |
376 | 400 | ||
377 | /* | 401 | /* |
378 | * allocate new fragment | 402 | * allocate new fragment |
@@ -380,14 +404,16 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, | |||
380 | if (oldcount == 0) { | 404 | if (oldcount == 0) { |
381 | result = ufs_alloc_fragments (inode, cgno, goal, count, err); | 405 | result = ufs_alloc_fragments (inode, cgno, goal, count, err); |
382 | if (result) { | 406 | if (result) { |
383 | *p = cpu_to_fs32(sb, result); | 407 | ufs_cpu_to_data_ptr(sb, p, result); |
384 | *err = 0; | 408 | *err = 0; |
385 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); | 409 | UFS_I(inode)->i_lastfrag = |
386 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, | 410 | max_t(u32, UFS_I(inode)->i_lastfrag, |
387 | locked_page != NULL); | 411 | fragment + count); |
412 | ufs_clear_frags(inode, result + oldcount, | ||
413 | newcount - oldcount, locked_page != NULL); | ||
388 | } | 414 | } |
389 | unlock_super(sb); | 415 | unlock_super(sb); |
390 | UFSD("EXIT, result %u\n", result); | 416 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
391 | return result; | 417 | return result; |
392 | } | 418 | } |
393 | 419 | ||
@@ -401,7 +427,7 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, | |||
401 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, | 427 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, |
402 | locked_page != NULL); | 428 | locked_page != NULL); |
403 | unlock_super(sb); | 429 | unlock_super(sb); |
404 | UFSD("EXIT, result %u\n", result); | 430 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
405 | return result; | 431 | return result; |
406 | } | 432 | } |
407 | 433 | ||
@@ -433,15 +459,14 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, | |||
433 | locked_page != NULL); | 459 | locked_page != NULL); |
434 | ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp, | 460 | ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp, |
435 | result, locked_page); | 461 | result, locked_page); |
436 | 462 | ufs_cpu_to_data_ptr(sb, p, result); | |
437 | *p = cpu_to_fs32(sb, result); | ||
438 | *err = 0; | 463 | *err = 0; |
439 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); | 464 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); |
440 | unlock_super(sb); | 465 | unlock_super(sb); |
441 | if (newcount < request) | 466 | if (newcount < request) |
442 | ufs_free_fragments (inode, result + newcount, request - newcount); | 467 | ufs_free_fragments (inode, result + newcount, request - newcount); |
443 | ufs_free_fragments (inode, tmp, oldcount); | 468 | ufs_free_fragments (inode, tmp, oldcount); |
444 | UFSD("EXIT, result %u\n", result); | 469 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
445 | return result; | 470 | return result; |
446 | } | 471 | } |
447 | 472 | ||
@@ -450,9 +475,8 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, | |||
450 | return 0; | 475 | return 0; |
451 | } | 476 | } |
452 | 477 | ||
453 | static unsigned | 478 | static u64 ufs_add_fragments(struct inode *inode, u64 fragment, |
454 | ufs_add_fragments (struct inode * inode, unsigned fragment, | 479 | unsigned oldcount, unsigned newcount, int *err) |
455 | unsigned oldcount, unsigned newcount, int * err) | ||
456 | { | 480 | { |
457 | struct super_block * sb; | 481 | struct super_block * sb; |
458 | struct ufs_sb_private_info * uspi; | 482 | struct ufs_sb_private_info * uspi; |
@@ -461,14 +485,15 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, | |||
461 | struct ufs_cylinder_group * ucg; | 485 | struct ufs_cylinder_group * ucg; |
462 | unsigned cgno, fragno, fragoff, count, fragsize, i; | 486 | unsigned cgno, fragno, fragoff, count, fragsize, i; |
463 | 487 | ||
464 | UFSD("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount); | 488 | UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n", |
489 | (unsigned long long)fragment, oldcount, newcount); | ||
465 | 490 | ||
466 | sb = inode->i_sb; | 491 | sb = inode->i_sb; |
467 | uspi = UFS_SB(sb)->s_uspi; | 492 | uspi = UFS_SB(sb)->s_uspi; |
468 | usb1 = ubh_get_usb_first (uspi); | 493 | usb1 = ubh_get_usb_first (uspi); |
469 | count = newcount - oldcount; | 494 | count = newcount - oldcount; |
470 | 495 | ||
471 | cgno = ufs_dtog(fragment); | 496 | cgno = ufs_dtog(uspi, fragment); |
472 | if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count) | 497 | if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count) |
473 | return 0; | 498 | return 0; |
474 | if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb) | 499 | if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb) |
@@ -483,7 +508,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, | |||
483 | return 0; | 508 | return 0; |
484 | } | 509 | } |
485 | 510 | ||
486 | fragno = ufs_dtogd (fragment); | 511 | fragno = ufs_dtogd(uspi, fragment); |
487 | fragoff = ufs_fragnum (fragno); | 512 | fragoff = ufs_fragnum (fragno); |
488 | for (i = oldcount; i < newcount; i++) | 513 | for (i = oldcount; i < newcount; i++) |
489 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) | 514 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) |
@@ -521,7 +546,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, | |||
521 | } | 546 | } |
522 | sb->s_dirt = 1; | 547 | sb->s_dirt = 1; |
523 | 548 | ||
524 | UFSD("EXIT, fragment %u\n", fragment); | 549 | UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment); |
525 | 550 | ||
526 | return fragment; | 551 | return fragment; |
527 | } | 552 | } |
@@ -534,17 +559,19 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, | |||
534 | if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \ | 559 | if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \ |
535 | goto cg_found; | 560 | goto cg_found; |
536 | 561 | ||
537 | static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno, | 562 | static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno, |
538 | unsigned goal, unsigned count, int * err) | 563 | u64 goal, unsigned count, int *err) |
539 | { | 564 | { |
540 | struct super_block * sb; | 565 | struct super_block * sb; |
541 | struct ufs_sb_private_info * uspi; | 566 | struct ufs_sb_private_info * uspi; |
542 | struct ufs_super_block_first * usb1; | 567 | struct ufs_super_block_first * usb1; |
543 | struct ufs_cg_private_info * ucpi; | 568 | struct ufs_cg_private_info * ucpi; |
544 | struct ufs_cylinder_group * ucg; | 569 | struct ufs_cylinder_group * ucg; |
545 | unsigned oldcg, i, j, k, result, allocsize; | 570 | unsigned oldcg, i, j, k, allocsize; |
571 | u64 result; | ||
546 | 572 | ||
547 | UFSD("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count); | 573 | UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n", |
574 | inode->i_ino, cgno, (unsigned long long)goal, count); | ||
548 | 575 | ||
549 | sb = inode->i_sb; | 576 | sb = inode->i_sb; |
550 | uspi = UFS_SB(sb)->s_uspi; | 577 | uspi = UFS_SB(sb)->s_uspi; |
@@ -593,7 +620,7 @@ cg_found: | |||
593 | 620 | ||
594 | if (count == uspi->s_fpb) { | 621 | if (count == uspi->s_fpb) { |
595 | result = ufs_alloccg_block (inode, ucpi, goal, err); | 622 | result = ufs_alloccg_block (inode, ucpi, goal, err); |
596 | if (result == (unsigned)-1) | 623 | if (result == INVBLOCK) |
597 | return 0; | 624 | return 0; |
598 | goto succed; | 625 | goto succed; |
599 | } | 626 | } |
@@ -604,9 +631,9 @@ cg_found: | |||
604 | 631 | ||
605 | if (allocsize == uspi->s_fpb) { | 632 | if (allocsize == uspi->s_fpb) { |
606 | result = ufs_alloccg_block (inode, ucpi, goal, err); | 633 | result = ufs_alloccg_block (inode, ucpi, goal, err); |
607 | if (result == (unsigned)-1) | 634 | if (result == INVBLOCK) |
608 | return 0; | 635 | return 0; |
609 | goal = ufs_dtogd (result); | 636 | goal = ufs_dtogd(uspi, result); |
610 | for (i = count; i < uspi->s_fpb; i++) | 637 | for (i = count; i < uspi->s_fpb; i++) |
611 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); | 638 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); |
612 | i = uspi->s_fpb - count; | 639 | i = uspi->s_fpb - count; |
@@ -620,7 +647,7 @@ cg_found: | |||
620 | } | 647 | } |
621 | 648 | ||
622 | result = ufs_bitmap_search (sb, ucpi, goal, allocsize); | 649 | result = ufs_bitmap_search (sb, ucpi, goal, allocsize); |
623 | if (result == (unsigned)-1) | 650 | if (result == INVBLOCK) |
624 | return 0; | 651 | return 0; |
625 | if(DQUOT_ALLOC_BLOCK(inode, count)) { | 652 | if(DQUOT_ALLOC_BLOCK(inode, count)) { |
626 | *err = -EDQUOT; | 653 | *err = -EDQUOT; |
@@ -647,20 +674,21 @@ succed: | |||
647 | sb->s_dirt = 1; | 674 | sb->s_dirt = 1; |
648 | 675 | ||
649 | result += cgno * uspi->s_fpg; | 676 | result += cgno * uspi->s_fpg; |
650 | UFSD("EXIT3, result %u\n", result); | 677 | UFSD("EXIT3, result %llu\n", (unsigned long long)result); |
651 | return result; | 678 | return result; |
652 | } | 679 | } |
653 | 680 | ||
654 | static unsigned ufs_alloccg_block (struct inode * inode, | 681 | static u64 ufs_alloccg_block(struct inode *inode, |
655 | struct ufs_cg_private_info * ucpi, unsigned goal, int * err) | 682 | struct ufs_cg_private_info *ucpi, |
683 | u64 goal, int *err) | ||
656 | { | 684 | { |
657 | struct super_block * sb; | 685 | struct super_block * sb; |
658 | struct ufs_sb_private_info * uspi; | 686 | struct ufs_sb_private_info * uspi; |
659 | struct ufs_super_block_first * usb1; | 687 | struct ufs_super_block_first * usb1; |
660 | struct ufs_cylinder_group * ucg; | 688 | struct ufs_cylinder_group * ucg; |
661 | unsigned result, cylno, blkno; | 689 | u64 result, blkno; |
662 | 690 | ||
663 | UFSD("ENTER, goal %u\n", goal); | 691 | UFSD("ENTER, goal %llu\n", (unsigned long long)goal); |
664 | 692 | ||
665 | sb = inode->i_sb; | 693 | sb = inode->i_sb; |
666 | uspi = UFS_SB(sb)->s_uspi; | 694 | uspi = UFS_SB(sb)->s_uspi; |
@@ -672,7 +700,7 @@ static unsigned ufs_alloccg_block (struct inode * inode, | |||
672 | goto norot; | 700 | goto norot; |
673 | } | 701 | } |
674 | goal = ufs_blknum (goal); | 702 | goal = ufs_blknum (goal); |
675 | goal = ufs_dtogd (goal); | 703 | goal = ufs_dtogd(uspi, goal); |
676 | 704 | ||
677 | /* | 705 | /* |
678 | * If the requested block is available, use it. | 706 | * If the requested block is available, use it. |
@@ -684,8 +712,8 @@ static unsigned ufs_alloccg_block (struct inode * inode, | |||
684 | 712 | ||
685 | norot: | 713 | norot: |
686 | result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb); | 714 | result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb); |
687 | if (result == (unsigned)-1) | 715 | if (result == INVBLOCK) |
688 | return (unsigned)-1; | 716 | return INVBLOCK; |
689 | ucpi->c_rotor = result; | 717 | ucpi->c_rotor = result; |
690 | gotit: | 718 | gotit: |
691 | blkno = ufs_fragstoblks(result); | 719 | blkno = ufs_fragstoblks(result); |
@@ -694,17 +722,22 @@ gotit: | |||
694 | ufs_clusteracct (sb, ucpi, blkno, -1); | 722 | ufs_clusteracct (sb, ucpi, blkno, -1); |
695 | if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) { | 723 | if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) { |
696 | *err = -EDQUOT; | 724 | *err = -EDQUOT; |
697 | return (unsigned)-1; | 725 | return INVBLOCK; |
698 | } | 726 | } |
699 | 727 | ||
700 | fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1); | 728 | fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1); |
701 | uspi->cs_total.cs_nbfree--; | 729 | uspi->cs_total.cs_nbfree--; |
702 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1); | 730 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1); |
703 | cylno = ufs_cbtocylno(result); | 731 | |
704 | fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1); | 732 | if (uspi->fs_magic != UFS2_MAGIC) { |
705 | fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1); | 733 | unsigned cylno = ufs_cbtocylno((unsigned)result); |
734 | |||
735 | fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, | ||
736 | ufs_cbtorpos((unsigned)result)), 1); | ||
737 | fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1); | ||
738 | } | ||
706 | 739 | ||
707 | UFSD("EXIT, result %u\n", result); | 740 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
708 | 741 | ||
709 | return result; | 742 | return result; |
710 | } | 743 | } |
@@ -744,9 +777,9 @@ static unsigned ubh_scanc(struct ufs_sb_private_info *uspi, | |||
744 | * @goal: near which block we want find new one | 777 | * @goal: near which block we want find new one |
745 | * @count: specified size | 778 | * @count: specified size |
746 | */ | 779 | */ |
747 | static unsigned ufs_bitmap_search(struct super_block *sb, | 780 | static u64 ufs_bitmap_search(struct super_block *sb, |
748 | struct ufs_cg_private_info *ucpi, | 781 | struct ufs_cg_private_info *ucpi, |
749 | unsigned goal, unsigned count) | 782 | u64 goal, unsigned count) |
750 | { | 783 | { |
751 | /* | 784 | /* |
752 | * Bit patterns for identifying fragments in the block map | 785 | * Bit patterns for identifying fragments in the block map |
@@ -761,16 +794,18 @@ static unsigned ufs_bitmap_search(struct super_block *sb, | |||
761 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 794 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
762 | struct ufs_super_block_first *usb1; | 795 | struct ufs_super_block_first *usb1; |
763 | struct ufs_cylinder_group *ucg; | 796 | struct ufs_cylinder_group *ucg; |
764 | unsigned start, length, loc, result; | 797 | unsigned start, length, loc; |
765 | unsigned pos, want, blockmap, mask, end; | 798 | unsigned pos, want, blockmap, mask, end; |
799 | u64 result; | ||
766 | 800 | ||
767 | UFSD("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count); | 801 | UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx, |
802 | (unsigned long long)goal, count); | ||
768 | 803 | ||
769 | usb1 = ubh_get_usb_first (uspi); | 804 | usb1 = ubh_get_usb_first (uspi); |
770 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 805 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); |
771 | 806 | ||
772 | if (goal) | 807 | if (goal) |
773 | start = ufs_dtogd(goal) >> 3; | 808 | start = ufs_dtogd(uspi, goal) >> 3; |
774 | else | 809 | else |
775 | start = ucpi->c_frotor >> 3; | 810 | start = ucpi->c_frotor >> 3; |
776 | 811 | ||
@@ -790,7 +825,7 @@ static unsigned ufs_bitmap_search(struct super_block *sb, | |||
790 | " length %u, count %u, freeoff %u\n", | 825 | " length %u, count %u, freeoff %u\n", |
791 | ucpi->c_cgx, start, length, count, | 826 | ucpi->c_cgx, start, length, count, |
792 | ucpi->c_freeoff); | 827 | ucpi->c_freeoff); |
793 | return (unsigned)-1; | 828 | return INVBLOCK; |
794 | } | 829 | } |
795 | start = 0; | 830 | start = 0; |
796 | } | 831 | } |
@@ -808,7 +843,8 @@ static unsigned ufs_bitmap_search(struct super_block *sb, | |||
808 | want = want_arr[count]; | 843 | want = want_arr[count]; |
809 | for (pos = 0; pos <= uspi->s_fpb - count; pos++) { | 844 | for (pos = 0; pos <= uspi->s_fpb - count; pos++) { |
810 | if ((blockmap & mask) == want) { | 845 | if ((blockmap & mask) == want) { |
811 | UFSD("EXIT, result %u\n", result); | 846 | UFSD("EXIT, result %llu\n", |
847 | (unsigned long long)result); | ||
812 | return result + pos; | 848 | return result + pos; |
813 | } | 849 | } |
814 | mask <<= 1; | 850 | mask <<= 1; |
@@ -819,7 +855,7 @@ static unsigned ufs_bitmap_search(struct super_block *sb, | |||
819 | ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n", | 855 | ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n", |
820 | ucpi->c_cgx); | 856 | ucpi->c_cgx); |
821 | UFSD("EXIT (FAILED)\n"); | 857 | UFSD("EXIT (FAILED)\n"); |
822 | return (unsigned)-1; | 858 | return INVBLOCK; |
823 | } | 859 | } |
824 | 860 | ||
825 | static void ufs_clusteracct(struct super_block * sb, | 861 | static void ufs_clusteracct(struct super_block * sb, |
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 433b6f68403a..4890ddf1518e 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/ufs_fs.h> | 21 | #include <linux/ufs_fs.h> |
22 | #include <linux/smp_lock.h> | 22 | #include <linux/smp_lock.h> |
23 | #include <linux/sched.h> | ||
24 | 23 | ||
25 | #include "swab.h" | 24 | #include "swab.h" |
26 | #include "util.h" | 25 | #include "util.h" |
@@ -106,12 +105,13 @@ static void ufs_check_page(struct page *page) | |||
106 | char *kaddr = page_address(page); | 105 | char *kaddr = page_address(page); |
107 | unsigned offs, rec_len; | 106 | unsigned offs, rec_len; |
108 | unsigned limit = PAGE_CACHE_SIZE; | 107 | unsigned limit = PAGE_CACHE_SIZE; |
108 | const unsigned chunk_mask = UFS_SB(sb)->s_uspi->s_dirblksize - 1; | ||
109 | struct ufs_dir_entry *p; | 109 | struct ufs_dir_entry *p; |
110 | char *error; | 110 | char *error; |
111 | 111 | ||
112 | if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) { | 112 | if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) { |
113 | limit = dir->i_size & ~PAGE_CACHE_MASK; | 113 | limit = dir->i_size & ~PAGE_CACHE_MASK; |
114 | if (limit & (UFS_SECTOR_SIZE - 1)) | 114 | if (limit & chunk_mask) |
115 | goto Ebadsize; | 115 | goto Ebadsize; |
116 | if (!limit) | 116 | if (!limit) |
117 | goto out; | 117 | goto out; |
@@ -126,7 +126,7 @@ static void ufs_check_page(struct page *page) | |||
126 | goto Ealign; | 126 | goto Ealign; |
127 | if (rec_len < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, p))) | 127 | if (rec_len < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, p))) |
128 | goto Enamelen; | 128 | goto Enamelen; |
129 | if (((offs + rec_len - 1) ^ offs) & ~(UFS_SECTOR_SIZE-1)) | 129 | if (((offs + rec_len - 1) ^ offs) & ~chunk_mask) |
130 | goto Espan; | 130 | goto Espan; |
131 | if (fs32_to_cpu(sb, p->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg * | 131 | if (fs32_to_cpu(sb, p->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg * |
132 | UFS_SB(sb)->s_uspi->s_ncg)) | 132 | UFS_SB(sb)->s_uspi->s_ncg)) |
@@ -310,6 +310,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) | |||
310 | int namelen = dentry->d_name.len; | 310 | int namelen = dentry->d_name.len; |
311 | struct super_block *sb = dir->i_sb; | 311 | struct super_block *sb = dir->i_sb; |
312 | unsigned reclen = UFS_DIR_REC_LEN(namelen); | 312 | unsigned reclen = UFS_DIR_REC_LEN(namelen); |
313 | const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize; | ||
313 | unsigned short rec_len, name_len; | 314 | unsigned short rec_len, name_len; |
314 | struct page *page = NULL; | 315 | struct page *page = NULL; |
315 | struct ufs_dir_entry *de; | 316 | struct ufs_dir_entry *de; |
@@ -342,8 +343,8 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) | |||
342 | if ((char *)de == dir_end) { | 343 | if ((char *)de == dir_end) { |
343 | /* We hit i_size */ | 344 | /* We hit i_size */ |
344 | name_len = 0; | 345 | name_len = 0; |
345 | rec_len = UFS_SECTOR_SIZE; | 346 | rec_len = chunk_size; |
346 | de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE); | 347 | de->d_reclen = cpu_to_fs16(sb, chunk_size); |
347 | de->d_ino = 0; | 348 | de->d_ino = 0; |
348 | goto got_it; | 349 | goto got_it; |
349 | } | 350 | } |
@@ -431,7 +432,7 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
431 | unsigned int offset = pos & ~PAGE_CACHE_MASK; | 432 | unsigned int offset = pos & ~PAGE_CACHE_MASK; |
432 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 433 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
433 | unsigned long npages = ufs_dir_pages(inode); | 434 | unsigned long npages = ufs_dir_pages(inode); |
434 | unsigned chunk_mask = ~(UFS_SECTOR_SIZE - 1); | 435 | unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); |
435 | int need_revalidate = filp->f_version != inode->i_version; | 436 | int need_revalidate = filp->f_version != inode->i_version; |
436 | unsigned flags = UFS_SB(sb)->s_flags; | 437 | unsigned flags = UFS_SB(sb)->s_flags; |
437 | 438 | ||
@@ -511,7 +512,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, | |||
511 | struct super_block *sb = inode->i_sb; | 512 | struct super_block *sb = inode->i_sb; |
512 | struct address_space *mapping = page->mapping; | 513 | struct address_space *mapping = page->mapping; |
513 | char *kaddr = page_address(page); | 514 | char *kaddr = page_address(page); |
514 | unsigned from = ((char*)dir - kaddr) & ~(UFS_SECTOR_SIZE - 1); | 515 | unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); |
515 | unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen); | 516 | unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen); |
516 | struct ufs_dir_entry *pde = NULL; | 517 | struct ufs_dir_entry *pde = NULL; |
517 | struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from); | 518 | struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from); |
@@ -556,6 +557,7 @@ int ufs_make_empty(struct inode * inode, struct inode *dir) | |||
556 | struct super_block * sb = dir->i_sb; | 557 | struct super_block * sb = dir->i_sb; |
557 | struct address_space *mapping = inode->i_mapping; | 558 | struct address_space *mapping = inode->i_mapping; |
558 | struct page *page = grab_cache_page(mapping, 0); | 559 | struct page *page = grab_cache_page(mapping, 0); |
560 | const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize; | ||
559 | struct ufs_dir_entry * de; | 561 | struct ufs_dir_entry * de; |
560 | char *base; | 562 | char *base; |
561 | int err; | 563 | int err; |
@@ -563,7 +565,7 @@ int ufs_make_empty(struct inode * inode, struct inode *dir) | |||
563 | if (!page) | 565 | if (!page) |
564 | return -ENOMEM; | 566 | return -ENOMEM; |
565 | kmap(page); | 567 | kmap(page); |
566 | err = mapping->a_ops->prepare_write(NULL, page, 0, UFS_SECTOR_SIZE); | 568 | err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size); |
567 | if (err) { | 569 | if (err) { |
568 | unlock_page(page); | 570 | unlock_page(page); |
569 | goto fail; | 571 | goto fail; |
@@ -584,11 +586,11 @@ int ufs_make_empty(struct inode * inode, struct inode *dir) | |||
584 | ((char *)de + fs16_to_cpu(sb, de->d_reclen)); | 586 | ((char *)de + fs16_to_cpu(sb, de->d_reclen)); |
585 | de->d_ino = cpu_to_fs32(sb, dir->i_ino); | 587 | de->d_ino = cpu_to_fs32(sb, dir->i_ino); |
586 | ufs_set_de_type(sb, de, dir->i_mode); | 588 | ufs_set_de_type(sb, de, dir->i_mode); |
587 | de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1)); | 589 | de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1)); |
588 | ufs_set_de_namlen(sb, de, 2); | 590 | ufs_set_de_namlen(sb, de, 2); |
589 | strcpy (de->d_name, ".."); | 591 | strcpy (de->d_name, ".."); |
590 | 592 | ||
591 | err = ufs_commit_chunk(page, 0, UFS_SECTOR_SIZE); | 593 | err = ufs_commit_chunk(page, 0, chunk_size); |
592 | fail: | 594 | fail: |
593 | kunmap(page); | 595 | kunmap(page); |
594 | page_cache_release(page); | 596 | page_cache_release(page); |
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 2ad1259c6eca..b868878009b6 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c | |||
@@ -18,6 +18,9 @@ | |||
18 | * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 | 18 | * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 |
19 | * Big-endian to little-endian byte-swapping/bitmaps by | 19 | * Big-endian to little-endian byte-swapping/bitmaps by |
20 | * David S. Miller (davem@caip.rutgers.edu), 1995 | 20 | * David S. Miller (davem@caip.rutgers.edu), 1995 |
21 | * | ||
22 | * UFS2 write support added by | ||
23 | * Evgeniy Dushistov <dushistov@mail.ru>, 2007 | ||
21 | */ | 24 | */ |
22 | 25 | ||
23 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
@@ -126,6 +129,47 @@ void ufs_free_inode (struct inode * inode) | |||
126 | } | 129 | } |
127 | 130 | ||
128 | /* | 131 | /* |
132 | * Nullify new chunk of inodes, | ||
133 | * BSD people also set ui_gen field of inode | ||
134 | * during nullification, but we not care about | ||
135 | * that because of linux ufs do not support NFS | ||
136 | */ | ||
137 | static void ufs2_init_inodes_chunk(struct super_block *sb, | ||
138 | struct ufs_cg_private_info *ucpi, | ||
139 | struct ufs_cylinder_group *ucg) | ||
140 | { | ||
141 | struct buffer_head *bh; | ||
142 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
143 | sector_t beg = uspi->s_sbbase + | ||
144 | ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg + | ||
145 | fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk)); | ||
146 | sector_t end = beg + uspi->s_fpb; | ||
147 | |||
148 | UFSD("ENTER cgno %d\n", ucpi->c_cgx); | ||
149 | |||
150 | for (; beg < end; ++beg) { | ||
151 | bh = sb_getblk(sb, beg); | ||
152 | lock_buffer(bh); | ||
153 | memset(bh->b_data, 0, sb->s_blocksize); | ||
154 | set_buffer_uptodate(bh); | ||
155 | mark_buffer_dirty(bh); | ||
156 | unlock_buffer(bh); | ||
157 | if (sb->s_flags & MS_SYNCHRONOUS) | ||
158 | sync_dirty_buffer(bh); | ||
159 | brelse(bh); | ||
160 | } | ||
161 | |||
162 | fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb); | ||
163 | ubh_mark_buffer_dirty(UCPI_UBH(ucpi)); | ||
164 | if (sb->s_flags & MS_SYNCHRONOUS) { | ||
165 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | ||
166 | ubh_wait_on_buffer(UCPI_UBH(ucpi)); | ||
167 | } | ||
168 | |||
169 | UFSD("EXIT\n"); | ||
170 | } | ||
171 | |||
172 | /* | ||
129 | * There are two policies for allocating an inode. If the new inode is | 173 | * There are two policies for allocating an inode. If the new inode is |
130 | * a directory, then a forward search is made for a block group with both | 174 | * a directory, then a forward search is made for a block group with both |
131 | * free space and a low directory-to-inode ratio; if that fails, then of | 175 | * free space and a low directory-to-inode ratio; if that fails, then of |
@@ -146,6 +190,7 @@ struct inode * ufs_new_inode(struct inode * dir, int mode) | |||
146 | struct inode * inode; | 190 | struct inode * inode; |
147 | unsigned cg, bit, i, j, start; | 191 | unsigned cg, bit, i, j, start; |
148 | struct ufs_inode_info *ufsi; | 192 | struct ufs_inode_info *ufsi; |
193 | int err = -ENOSPC; | ||
149 | 194 | ||
150 | UFSD("ENTER\n"); | 195 | UFSD("ENTER\n"); |
151 | 196 | ||
@@ -198,13 +243,15 @@ struct inode * ufs_new_inode(struct inode * dir, int mode) | |||
198 | goto cg_found; | 243 | goto cg_found; |
199 | } | 244 | } |
200 | } | 245 | } |
201 | 246 | ||
202 | goto failed; | 247 | goto failed; |
203 | 248 | ||
204 | cg_found: | 249 | cg_found: |
205 | ucpi = ufs_load_cylinder (sb, cg); | 250 | ucpi = ufs_load_cylinder (sb, cg); |
206 | if (!ucpi) | 251 | if (!ucpi) { |
252 | err = -EIO; | ||
207 | goto failed; | 253 | goto failed; |
254 | } | ||
208 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 255 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); |
209 | if (!ufs_cg_chkmagic(sb, ucg)) | 256 | if (!ufs_cg_chkmagic(sb, ucg)) |
210 | ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number"); | 257 | ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number"); |
@@ -216,6 +263,7 @@ cg_found: | |||
216 | if (!(bit < start)) { | 263 | if (!(bit < start)) { |
217 | ufs_error (sb, "ufs_new_inode", | 264 | ufs_error (sb, "ufs_new_inode", |
218 | "cylinder group %u corrupted - error in inode bitmap\n", cg); | 265 | "cylinder group %u corrupted - error in inode bitmap\n", cg); |
266 | err = -EIO; | ||
219 | goto failed; | 267 | goto failed; |
220 | } | 268 | } |
221 | } | 269 | } |
@@ -224,9 +272,18 @@ cg_found: | |||
224 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); | 272 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); |
225 | else { | 273 | else { |
226 | ufs_panic (sb, "ufs_new_inode", "internal error"); | 274 | ufs_panic (sb, "ufs_new_inode", "internal error"); |
275 | err = -EIO; | ||
227 | goto failed; | 276 | goto failed; |
228 | } | 277 | } |
229 | 278 | ||
279 | if (uspi->fs_magic == UFS2_MAGIC) { | ||
280 | u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk); | ||
281 | |||
282 | if (bit + uspi->s_inopb > initediblk && | ||
283 | initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk)) | ||
284 | ufs2_init_inodes_chunk(sb, ucpi, ucg); | ||
285 | } | ||
286 | |||
230 | fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1); | 287 | fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1); |
231 | uspi->cs_total.cs_nifree--; | 288 | uspi->cs_total.cs_nifree--; |
232 | fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1); | 289 | fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1); |
@@ -236,7 +293,6 @@ cg_found: | |||
236 | uspi->cs_total.cs_ndir++; | 293 | uspi->cs_total.cs_ndir++; |
237 | fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1); | 294 | fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1); |
238 | } | 295 | } |
239 | |||
240 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 296 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
241 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 297 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
242 | if (sb->s_flags & MS_SYNCHRONOUS) { | 298 | if (sb->s_flags & MS_SYNCHRONOUS) { |
@@ -245,6 +301,7 @@ cg_found: | |||
245 | } | 301 | } |
246 | sb->s_dirt = 1; | 302 | sb->s_dirt = 1; |
247 | 303 | ||
304 | inode->i_ino = cg * uspi->s_ipg + bit; | ||
248 | inode->i_mode = mode; | 305 | inode->i_mode = mode; |
249 | inode->i_uid = current->fsuid; | 306 | inode->i_uid = current->fsuid; |
250 | if (dir->i_mode & S_ISGID) { | 307 | if (dir->i_mode & S_ISGID) { |
@@ -254,39 +311,72 @@ cg_found: | |||
254 | } else | 311 | } else |
255 | inode->i_gid = current->fsgid; | 312 | inode->i_gid = current->fsgid; |
256 | 313 | ||
257 | inode->i_ino = cg * uspi->s_ipg + bit; | ||
258 | inode->i_blocks = 0; | 314 | inode->i_blocks = 0; |
315 | inode->i_generation = 0; | ||
259 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | 316 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; |
260 | ufsi->i_flags = UFS_I(dir)->i_flags; | 317 | ufsi->i_flags = UFS_I(dir)->i_flags; |
261 | ufsi->i_lastfrag = 0; | 318 | ufsi->i_lastfrag = 0; |
262 | ufsi->i_gen = 0; | ||
263 | ufsi->i_shadow = 0; | 319 | ufsi->i_shadow = 0; |
264 | ufsi->i_osync = 0; | 320 | ufsi->i_osync = 0; |
265 | ufsi->i_oeftflag = 0; | 321 | ufsi->i_oeftflag = 0; |
266 | ufsi->i_dir_start_lookup = 0; | 322 | ufsi->i_dir_start_lookup = 0; |
267 | memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1)); | 323 | memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1)); |
268 | |||
269 | insert_inode_hash(inode); | 324 | insert_inode_hash(inode); |
270 | mark_inode_dirty(inode); | 325 | mark_inode_dirty(inode); |
271 | 326 | ||
327 | if (uspi->fs_magic == UFS2_MAGIC) { | ||
328 | struct buffer_head *bh; | ||
329 | struct ufs2_inode *ufs2_inode; | ||
330 | |||
331 | /* | ||
332 | * setup birth date, we do it here because of there is no sense | ||
333 | * to hold it in struct ufs_inode_info, and lose 64 bit | ||
334 | */ | ||
335 | bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); | ||
336 | if (!bh) { | ||
337 | ufs_warning(sb, "ufs_read_inode", | ||
338 | "unable to read inode %lu\n", | ||
339 | inode->i_ino); | ||
340 | err = -EIO; | ||
341 | goto fail_remove_inode; | ||
342 | } | ||
343 | lock_buffer(bh); | ||
344 | ufs2_inode = (struct ufs2_inode *)bh->b_data; | ||
345 | ufs2_inode += ufs_inotofsbo(inode->i_ino); | ||
346 | ufs2_inode->ui_birthtime.tv_sec = | ||
347 | cpu_to_fs32(sb, CURRENT_TIME_SEC.tv_sec); | ||
348 | ufs2_inode->ui_birthtime.tv_usec = 0; | ||
349 | mark_buffer_dirty(bh); | ||
350 | unlock_buffer(bh); | ||
351 | if (sb->s_flags & MS_SYNCHRONOUS) | ||
352 | sync_dirty_buffer(bh); | ||
353 | brelse(bh); | ||
354 | } | ||
355 | |||
272 | unlock_super (sb); | 356 | unlock_super (sb); |
273 | 357 | ||
274 | if (DQUOT_ALLOC_INODE(inode)) { | 358 | if (DQUOT_ALLOC_INODE(inode)) { |
275 | DQUOT_DROP(inode); | 359 | DQUOT_DROP(inode); |
276 | inode->i_flags |= S_NOQUOTA; | 360 | err = -EDQUOT; |
277 | inode->i_nlink = 0; | 361 | goto fail_without_unlock; |
278 | iput(inode); | ||
279 | return ERR_PTR(-EDQUOT); | ||
280 | } | 362 | } |
281 | 363 | ||
282 | UFSD("allocating inode %lu\n", inode->i_ino); | 364 | UFSD("allocating inode %lu\n", inode->i_ino); |
283 | UFSD("EXIT\n"); | 365 | UFSD("EXIT\n"); |
284 | return inode; | 366 | return inode; |
285 | 367 | ||
368 | fail_remove_inode: | ||
369 | unlock_super(sb); | ||
370 | fail_without_unlock: | ||
371 | inode->i_flags |= S_NOQUOTA; | ||
372 | inode->i_nlink = 0; | ||
373 | iput(inode); | ||
374 | UFSD("EXIT (FAILED): err %d\n", err); | ||
375 | return ERR_PTR(err); | ||
286 | failed: | 376 | failed: |
287 | unlock_super (sb); | 377 | unlock_super (sb); |
288 | make_bad_inode(inode); | 378 | make_bad_inode(inode); |
289 | iput (inode); | 379 | iput (inode); |
290 | UFSD("EXIT (FAILED)\n"); | 380 | UFSD("EXIT (FAILED): err %d\n", err); |
291 | return ERR_PTR(-ENOSPC); | 381 | return ERR_PTR(err); |
292 | } | 382 | } |
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 4295ca91cf85..fb34ad03e224 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
@@ -170,7 +170,7 @@ out: | |||
170 | * @locked_page - for ufs_new_fragments() | 170 | * @locked_page - for ufs_new_fragments() |
171 | */ | 171 | */ |
172 | static struct buffer_head * | 172 | static struct buffer_head * |
173 | ufs_inode_getfrag(struct inode *inode, unsigned int fragment, | 173 | ufs_inode_getfrag(struct inode *inode, u64 fragment, |
174 | sector_t new_fragment, unsigned int required, int *err, | 174 | sector_t new_fragment, unsigned int required, int *err, |
175 | long *phys, int *new, struct page *locked_page) | 175 | long *phys, int *new, struct page *locked_page) |
176 | { | 176 | { |
@@ -178,12 +178,12 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, | |||
178 | struct super_block *sb = inode->i_sb; | 178 | struct super_block *sb = inode->i_sb; |
179 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 179 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
180 | struct buffer_head * result; | 180 | struct buffer_head * result; |
181 | unsigned block, blockoff, lastfrag, lastblock, lastblockoff; | 181 | unsigned blockoff, lastblockoff; |
182 | unsigned tmp, goal; | 182 | u64 tmp, goal, lastfrag, block, lastblock; |
183 | __fs32 * p, * p2; | 183 | void *p, *p2; |
184 | 184 | ||
185 | UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, " | 185 | UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, " |
186 | "metadata %d\n", inode->i_ino, fragment, | 186 | "metadata %d\n", inode->i_ino, (unsigned long long)fragment, |
187 | (unsigned long long)new_fragment, required, !phys); | 187 | (unsigned long long)new_fragment, required, !phys); |
188 | 188 | ||
189 | /* TODO : to be done for write support | 189 | /* TODO : to be done for write support |
@@ -193,17 +193,20 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, | |||
193 | 193 | ||
194 | block = ufs_fragstoblks (fragment); | 194 | block = ufs_fragstoblks (fragment); |
195 | blockoff = ufs_fragnum (fragment); | 195 | blockoff = ufs_fragnum (fragment); |
196 | p = ufsi->i_u1.i_data + block; | 196 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); |
197 | |||
197 | goal = 0; | 198 | goal = 0; |
198 | 199 | ||
199 | repeat: | 200 | repeat: |
200 | tmp = fs32_to_cpu(sb, *p); | 201 | tmp = ufs_data_ptr_to_cpu(sb, p); |
202 | |||
201 | lastfrag = ufsi->i_lastfrag; | 203 | lastfrag = ufsi->i_lastfrag; |
202 | if (tmp && fragment < lastfrag) { | 204 | if (tmp && fragment < lastfrag) { |
203 | if (!phys) { | 205 | if (!phys) { |
204 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); | 206 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); |
205 | if (tmp == fs32_to_cpu(sb, *p)) { | 207 | if (tmp == ufs_data_ptr_to_cpu(sb, p)) { |
206 | UFSD("EXIT, result %u\n", tmp + blockoff); | 208 | UFSD("EXIT, result %llu\n", |
209 | (unsigned long long)tmp + blockoff); | ||
207 | return result; | 210 | return result; |
208 | } | 211 | } |
209 | brelse (result); | 212 | brelse (result); |
@@ -224,10 +227,11 @@ repeat: | |||
224 | * We must reallocate last allocated block | 227 | * We must reallocate last allocated block |
225 | */ | 228 | */ |
226 | if (lastblockoff) { | 229 | if (lastblockoff) { |
227 | p2 = ufsi->i_u1.i_data + lastblock; | 230 | p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock); |
228 | tmp = ufs_new_fragments (inode, p2, lastfrag, | 231 | tmp = ufs_new_fragments(inode, p2, lastfrag, |
229 | fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff, | 232 | ufs_data_ptr_to_cpu(sb, p2), |
230 | err, locked_page); | 233 | uspi->s_fpb - lastblockoff, |
234 | err, locked_page); | ||
231 | if (!tmp) { | 235 | if (!tmp) { |
232 | if (lastfrag != ufsi->i_lastfrag) | 236 | if (lastfrag != ufsi->i_lastfrag) |
233 | goto repeat; | 237 | goto repeat; |
@@ -237,27 +241,31 @@ repeat: | |||
237 | lastfrag = ufsi->i_lastfrag; | 241 | lastfrag = ufsi->i_lastfrag; |
238 | 242 | ||
239 | } | 243 | } |
240 | tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]); | 244 | tmp = ufs_data_ptr_to_cpu(sb, |
245 | ufs_get_direct_data_ptr(uspi, ufsi, | ||
246 | lastblock)); | ||
241 | if (tmp) | 247 | if (tmp) |
242 | goal = tmp + uspi->s_fpb; | 248 | goal = tmp + uspi->s_fpb; |
243 | tmp = ufs_new_fragments (inode, p, fragment - blockoff, | 249 | tmp = ufs_new_fragments (inode, p, fragment - blockoff, |
244 | goal, required + blockoff, | 250 | goal, required + blockoff, |
245 | err, | 251 | err, |
246 | phys != NULL ? locked_page : NULL); | 252 | phys != NULL ? locked_page : NULL); |
247 | } | 253 | } else if (lastblock == block) { |
248 | /* | 254 | /* |
249 | * We will extend last allocated block | 255 | * We will extend last allocated block |
250 | */ | 256 | */ |
251 | else if (lastblock == block) { | 257 | tmp = ufs_new_fragments(inode, p, fragment - |
252 | tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff), | 258 | (blockoff - lastblockoff), |
253 | fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), | 259 | ufs_data_ptr_to_cpu(sb, p), |
260 | required + (blockoff - lastblockoff), | ||
254 | err, phys != NULL ? locked_page : NULL); | 261 | err, phys != NULL ? locked_page : NULL); |
255 | } else /* (lastblock > block) */ { | 262 | } else /* (lastblock > block) */ { |
256 | /* | 263 | /* |
257 | * We will allocate new block before last allocated block | 264 | * We will allocate new block before last allocated block |
258 | */ | 265 | */ |
259 | if (block) { | 266 | if (block) { |
260 | tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[block-1]); | 267 | tmp = ufs_data_ptr_to_cpu(sb, |
268 | ufs_get_direct_data_ptr(uspi, ufsi, block - 1)); | ||
261 | if (tmp) | 269 | if (tmp) |
262 | goal = tmp + uspi->s_fpb; | 270 | goal = tmp + uspi->s_fpb; |
263 | } | 271 | } |
@@ -266,7 +274,7 @@ repeat: | |||
266 | phys != NULL ? locked_page : NULL); | 274 | phys != NULL ? locked_page : NULL); |
267 | } | 275 | } |
268 | if (!tmp) { | 276 | if (!tmp) { |
269 | if ((!blockoff && *p) || | 277 | if ((!blockoff && ufs_data_ptr_to_cpu(sb, p)) || |
270 | (blockoff && lastfrag != ufsi->i_lastfrag)) | 278 | (blockoff && lastfrag != ufsi->i_lastfrag)) |
271 | goto repeat; | 279 | goto repeat; |
272 | *err = -ENOSPC; | 280 | *err = -ENOSPC; |
@@ -286,7 +294,7 @@ repeat: | |||
286 | if (IS_SYNC(inode)) | 294 | if (IS_SYNC(inode)) |
287 | ufs_sync_inode (inode); | 295 | ufs_sync_inode (inode); |
288 | mark_inode_dirty(inode); | 296 | mark_inode_dirty(inode); |
289 | UFSD("EXIT, result %u\n", tmp + blockoff); | 297 | UFSD("EXIT, result %llu\n", (unsigned long long)tmp + blockoff); |
290 | return result; | 298 | return result; |
291 | 299 | ||
292 | /* This part : To be implemented .... | 300 | /* This part : To be implemented .... |
@@ -320,20 +328,22 @@ repeat2: | |||
320 | */ | 328 | */ |
321 | static struct buffer_head * | 329 | static struct buffer_head * |
322 | ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, | 330 | ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, |
323 | unsigned int fragment, sector_t new_fragment, int *err, | 331 | u64 fragment, sector_t new_fragment, int *err, |
324 | long *phys, int *new, struct page *locked_page) | 332 | long *phys, int *new, struct page *locked_page) |
325 | { | 333 | { |
326 | struct super_block *sb = inode->i_sb; | 334 | struct super_block *sb = inode->i_sb; |
327 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 335 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
328 | struct buffer_head * result; | 336 | struct buffer_head * result; |
329 | unsigned tmp, goal, block, blockoff; | 337 | unsigned blockoff; |
330 | __fs32 * p; | 338 | u64 tmp, goal, block; |
339 | void *p; | ||
331 | 340 | ||
332 | block = ufs_fragstoblks (fragment); | 341 | block = ufs_fragstoblks (fragment); |
333 | blockoff = ufs_fragnum (fragment); | 342 | blockoff = ufs_fragnum (fragment); |
334 | 343 | ||
335 | UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n", | 344 | UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, metadata %d\n", |
336 | inode->i_ino, fragment, (unsigned long long)new_fragment, !phys); | 345 | inode->i_ino, (unsigned long long)fragment, |
346 | (unsigned long long)new_fragment, !phys); | ||
337 | 347 | ||
338 | result = NULL; | 348 | result = NULL; |
339 | if (!bh) | 349 | if (!bh) |
@@ -344,14 +354,16 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, | |||
344 | if (!buffer_uptodate(bh)) | 354 | if (!buffer_uptodate(bh)) |
345 | goto out; | 355 | goto out; |
346 | } | 356 | } |
347 | 357 | if (uspi->fs_magic == UFS2_MAGIC) | |
348 | p = (__fs32 *) bh->b_data + block; | 358 | p = (__fs64 *)bh->b_data + block; |
359 | else | ||
360 | p = (__fs32 *)bh->b_data + block; | ||
349 | repeat: | 361 | repeat: |
350 | tmp = fs32_to_cpu(sb, *p); | 362 | tmp = ufs_data_ptr_to_cpu(sb, p); |
351 | if (tmp) { | 363 | if (tmp) { |
352 | if (!phys) { | 364 | if (!phys) { |
353 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); | 365 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); |
354 | if (tmp == fs32_to_cpu(sb, *p)) | 366 | if (tmp == ufs_data_ptr_to_cpu(sb, p)) |
355 | goto out; | 367 | goto out; |
356 | brelse (result); | 368 | brelse (result); |
357 | goto repeat; | 369 | goto repeat; |
@@ -361,14 +373,16 @@ repeat: | |||
361 | } | 373 | } |
362 | } | 374 | } |
363 | 375 | ||
364 | if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]))) | 376 | if (block && (uspi->fs_magic == UFS2_MAGIC ? |
377 | (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[block-1])) : | ||
378 | (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[block-1])))) | ||
365 | goal = tmp + uspi->s_fpb; | 379 | goal = tmp + uspi->s_fpb; |
366 | else | 380 | else |
367 | goal = bh->b_blocknr + uspi->s_fpb; | 381 | goal = bh->b_blocknr + uspi->s_fpb; |
368 | tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal, | 382 | tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal, |
369 | uspi->s_fpb, err, locked_page); | 383 | uspi->s_fpb, err, locked_page); |
370 | if (!tmp) { | 384 | if (!tmp) { |
371 | if (fs32_to_cpu(sb, *p)) | 385 | if (ufs_data_ptr_to_cpu(sb, p)) |
372 | goto repeat; | 386 | goto repeat; |
373 | goto out; | 387 | goto out; |
374 | } | 388 | } |
@@ -386,7 +400,7 @@ repeat: | |||
386 | sync_dirty_buffer(bh); | 400 | sync_dirty_buffer(bh); |
387 | inode->i_ctime = CURRENT_TIME_SEC; | 401 | inode->i_ctime = CURRENT_TIME_SEC; |
388 | mark_inode_dirty(inode); | 402 | mark_inode_dirty(inode); |
389 | UFSD("result %u\n", tmp + blockoff); | 403 | UFSD("result %llu\n", (unsigned long long)tmp + blockoff); |
390 | out: | 404 | out: |
391 | brelse (bh); | 405 | brelse (bh); |
392 | UFSD("EXIT\n"); | 406 | UFSD("EXIT\n"); |
@@ -616,8 +630,8 @@ static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) | |||
616 | inode->i_atime.tv_nsec = 0; | 630 | inode->i_atime.tv_nsec = 0; |
617 | inode->i_ctime.tv_nsec = 0; | 631 | inode->i_ctime.tv_nsec = 0; |
618 | inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks); | 632 | inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks); |
633 | inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen); | ||
619 | ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags); | 634 | ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags); |
620 | ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen); | ||
621 | ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); | 635 | ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); |
622 | ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); | 636 | ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); |
623 | 637 | ||
@@ -661,8 +675,8 @@ static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) | |||
661 | inode->i_atime.tv_nsec = 0; | 675 | inode->i_atime.tv_nsec = 0; |
662 | inode->i_ctime.tv_nsec = 0; | 676 | inode->i_ctime.tv_nsec = 0; |
663 | inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); | 677 | inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); |
678 | inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen); | ||
664 | ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); | 679 | ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); |
665 | ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen); | ||
666 | /* | 680 | /* |
667 | ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); | 681 | ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); |
668 | ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); | 682 | ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); |
@@ -731,34 +745,11 @@ bad_inode: | |||
731 | make_bad_inode(inode); | 745 | make_bad_inode(inode); |
732 | } | 746 | } |
733 | 747 | ||
734 | static int ufs_update_inode(struct inode * inode, int do_sync) | 748 | static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode) |
735 | { | 749 | { |
736 | struct ufs_inode_info *ufsi = UFS_I(inode); | 750 | struct super_block *sb = inode->i_sb; |
737 | struct super_block * sb; | 751 | struct ufs_inode_info *ufsi = UFS_I(inode); |
738 | struct ufs_sb_private_info * uspi; | 752 | unsigned i; |
739 | struct buffer_head * bh; | ||
740 | struct ufs_inode * ufs_inode; | ||
741 | unsigned i; | ||
742 | unsigned flags; | ||
743 | |||
744 | UFSD("ENTER, ino %lu\n", inode->i_ino); | ||
745 | |||
746 | sb = inode->i_sb; | ||
747 | uspi = UFS_SB(sb)->s_uspi; | ||
748 | flags = UFS_SB(sb)->s_flags; | ||
749 | |||
750 | if (inode->i_ino < UFS_ROOTINO || | ||
751 | inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { | ||
752 | ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); | ||
753 | return -1; | ||
754 | } | ||
755 | |||
756 | bh = sb_bread(sb, ufs_inotofsba(inode->i_ino)); | ||
757 | if (!bh) { | ||
758 | ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); | ||
759 | return -1; | ||
760 | } | ||
761 | ufs_inode = (struct ufs_inode *) (bh->b_data + ufs_inotofsbo(inode->i_ino) * sizeof(struct ufs_inode)); | ||
762 | 753 | ||
763 | ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); | 754 | ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); |
764 | ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); | 755 | ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); |
@@ -775,9 +766,9 @@ static int ufs_update_inode(struct inode * inode, int do_sync) | |||
775 | ufs_inode->ui_mtime.tv_usec = 0; | 766 | ufs_inode->ui_mtime.tv_usec = 0; |
776 | ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks); | 767 | ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks); |
777 | ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); | 768 | ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); |
778 | ufs_inode->ui_gen = cpu_to_fs32(sb, ufsi->i_gen); | 769 | ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation); |
779 | 770 | ||
780 | if ((flags & UFS_UID_MASK) == UFS_UID_EFT) { | 771 | if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) { |
781 | ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow); | 772 | ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow); |
782 | ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag); | 773 | ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag); |
783 | } | 774 | } |
@@ -796,6 +787,78 @@ static int ufs_update_inode(struct inode * inode, int do_sync) | |||
796 | 787 | ||
797 | if (!inode->i_nlink) | 788 | if (!inode->i_nlink) |
798 | memset (ufs_inode, 0, sizeof(struct ufs_inode)); | 789 | memset (ufs_inode, 0, sizeof(struct ufs_inode)); |
790 | } | ||
791 | |||
792 | static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode) | ||
793 | { | ||
794 | struct super_block *sb = inode->i_sb; | ||
795 | struct ufs_inode_info *ufsi = UFS_I(inode); | ||
796 | unsigned i; | ||
797 | |||
798 | UFSD("ENTER\n"); | ||
799 | ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); | ||
800 | ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); | ||
801 | |||
802 | ufs_inode->ui_uid = cpu_to_fs32(sb, inode->i_uid); | ||
803 | ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid); | ||
804 | |||
805 | ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); | ||
806 | ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec); | ||
807 | ufs_inode->ui_atime.tv_usec = 0; | ||
808 | ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec); | ||
809 | ufs_inode->ui_ctime.tv_usec = 0; | ||
810 | ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec); | ||
811 | ufs_inode->ui_mtime.tv_usec = 0; | ||
812 | |||
813 | ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks); | ||
814 | ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); | ||
815 | ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation); | ||
816 | |||
817 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { | ||
818 | /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ | ||
819 | ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0]; | ||
820 | } else if (inode->i_blocks) { | ||
821 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) | ||
822 | ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.u2_i_data[i]; | ||
823 | } else { | ||
824 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) | ||
825 | ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; | ||
826 | } | ||
827 | |||
828 | if (!inode->i_nlink) | ||
829 | memset (ufs_inode, 0, sizeof(struct ufs2_inode)); | ||
830 | UFSD("EXIT\n"); | ||
831 | } | ||
832 | |||
833 | static int ufs_update_inode(struct inode * inode, int do_sync) | ||
834 | { | ||
835 | struct super_block *sb = inode->i_sb; | ||
836 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
837 | struct buffer_head * bh; | ||
838 | |||
839 | UFSD("ENTER, ino %lu\n", inode->i_ino); | ||
840 | |||
841 | if (inode->i_ino < UFS_ROOTINO || | ||
842 | inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { | ||
843 | ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); | ||
844 | return -1; | ||
845 | } | ||
846 | |||
847 | bh = sb_bread(sb, ufs_inotofsba(inode->i_ino)); | ||
848 | if (!bh) { | ||
849 | ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); | ||
850 | return -1; | ||
851 | } | ||
852 | if (uspi->fs_magic == UFS2_MAGIC) { | ||
853 | struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; | ||
854 | |||
855 | ufs2_update_inode(inode, | ||
856 | ufs2_inode + ufs_inotofsbo(inode->i_ino)); | ||
857 | } else { | ||
858 | struct ufs_inode *ufs_inode = (struct ufs_inode *) bh->b_data; | ||
859 | |||
860 | ufs1_update_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino)); | ||
861 | } | ||
799 | 862 | ||
800 | mark_buffer_dirty(bh); | 863 | mark_buffer_dirty(bh); |
801 | if (do_sync) | 864 | if (do_sync) |
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index e84c0ecf0730..a059ccd064ea 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c | |||
@@ -355,7 +355,7 @@ out: | |||
355 | return err; | 355 | return err; |
356 | } | 356 | } |
357 | 357 | ||
358 | struct inode_operations ufs_dir_inode_operations = { | 358 | const struct inode_operations ufs_dir_inode_operations = { |
359 | .create = ufs_create, | 359 | .create = ufs_create, |
360 | .lookup = ufs_lookup, | 360 | .lookup = ufs_lookup, |
361 | .link = ufs_link, | 361 | .link = ufs_link, |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 8a8e9382ec09..b5a6461ec66b 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
@@ -61,6 +61,8 @@ | |||
61 | * UFS2 (of FreeBSD 5.x) support added by | 61 | * UFS2 (of FreeBSD 5.x) support added by |
62 | * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004 | 62 | * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004 |
63 | * | 63 | * |
64 | * UFS2 write support added by | ||
65 | * Evgeniy Dushistov <dushistov@mail.ru>, 2007 | ||
64 | */ | 66 | */ |
65 | 67 | ||
66 | 68 | ||
@@ -93,14 +95,16 @@ | |||
93 | /* | 95 | /* |
94 | * Print contents of ufs_super_block, useful for debugging | 96 | * Print contents of ufs_super_block, useful for debugging |
95 | */ | 97 | */ |
96 | static void ufs_print_super_stuff(struct super_block *sb, unsigned flags, | 98 | static void ufs_print_super_stuff(struct super_block *sb, |
97 | struct ufs_super_block_first *usb1, | 99 | struct ufs_super_block_first *usb1, |
98 | struct ufs_super_block_second *usb2, | 100 | struct ufs_super_block_second *usb2, |
99 | struct ufs_super_block_third *usb3) | 101 | struct ufs_super_block_third *usb3) |
100 | { | 102 | { |
103 | u32 magic = fs32_to_cpu(sb, usb3->fs_magic); | ||
104 | |||
101 | printk("ufs_print_super_stuff\n"); | 105 | printk("ufs_print_super_stuff\n"); |
102 | printk(" magic: 0x%x\n", fs32_to_cpu(sb, usb3->fs_magic)); | 106 | printk(" magic: 0x%x\n", magic); |
103 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { | 107 | if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) { |
104 | printk(" fs_size: %llu\n", (unsigned long long) | 108 | printk(" fs_size: %llu\n", (unsigned long long) |
105 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size)); | 109 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size)); |
106 | printk(" fs_dsize: %llu\n", (unsigned long long) | 110 | printk(" fs_dsize: %llu\n", (unsigned long long) |
@@ -117,6 +121,12 @@ static void ufs_print_super_stuff(struct super_block *sb, unsigned flags, | |||
117 | printk(" cs_nbfree(No of free blocks): %llu\n", | 121 | printk(" cs_nbfree(No of free blocks): %llu\n", |
118 | (unsigned long long) | 122 | (unsigned long long) |
119 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)); | 123 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)); |
124 | printk(KERN_INFO" cs_nifree(Num of free inodes): %llu\n", | ||
125 | (unsigned long long) | ||
126 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree)); | ||
127 | printk(KERN_INFO" cs_nffree(Num of free frags): %llu\n", | ||
128 | (unsigned long long) | ||
129 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree)); | ||
120 | } else { | 130 | } else { |
121 | printk(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno)); | 131 | printk(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno)); |
122 | printk(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno)); | 132 | printk(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno)); |
@@ -199,11 +209,11 @@ static void ufs_print_cylinder_stuff(struct super_block *sb, | |||
199 | printk("\n"); | 209 | printk("\n"); |
200 | } | 210 | } |
201 | #else | 211 | #else |
202 | # define ufs_print_super_stuff(sb, flags, usb1, usb2, usb3) /**/ | 212 | # define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/ |
203 | # define ufs_print_cylinder_stuff(sb, cg) /**/ | 213 | # define ufs_print_cylinder_stuff(sb, cg) /**/ |
204 | #endif /* CONFIG_UFS_DEBUG */ | 214 | #endif /* CONFIG_UFS_DEBUG */ |
205 | 215 | ||
206 | static struct super_operations ufs_super_ops; | 216 | static const struct super_operations ufs_super_ops; |
207 | 217 | ||
208 | static char error_buf[1024]; | 218 | static char error_buf[1024]; |
209 | 219 | ||
@@ -422,7 +432,6 @@ static int ufs_read_cylinder_structures(struct super_block *sb) | |||
422 | { | 432 | { |
423 | struct ufs_sb_info *sbi = UFS_SB(sb); | 433 | struct ufs_sb_info *sbi = UFS_SB(sb); |
424 | struct ufs_sb_private_info *uspi = sbi->s_uspi; | 434 | struct ufs_sb_private_info *uspi = sbi->s_uspi; |
425 | unsigned flags = sbi->s_flags; | ||
426 | struct ufs_buffer_head * ubh; | 435 | struct ufs_buffer_head * ubh; |
427 | unsigned char * base, * space; | 436 | unsigned char * base, * space; |
428 | unsigned size, blks, i; | 437 | unsigned size, blks, i; |
@@ -446,11 +455,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb) | |||
446 | if (i + uspi->s_fpb > blks) | 455 | if (i + uspi->s_fpb > blks) |
447 | size = (blks - i) * uspi->s_fsize; | 456 | size = (blks - i) * uspi->s_fsize; |
448 | 457 | ||
449 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) | 458 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); |
450 | ubh = ubh_bread(sb, | ||
451 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr) + i, size); | ||
452 | else | ||
453 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); | ||
454 | 459 | ||
455 | if (!ubh) | 460 | if (!ubh) |
456 | goto failed; | 461 | goto failed; |
@@ -545,6 +550,7 @@ static void ufs_put_cstotal(struct super_block *sb) | |||
545 | cpu_to_fs32(sb, uspi->cs_total.cs_nffree); | 550 | cpu_to_fs32(sb, uspi->cs_total.cs_nffree); |
546 | } | 551 | } |
547 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); | 552 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); |
553 | ufs_print_super_stuff(sb, usb1, usb2, usb3); | ||
548 | UFSD("EXIT\n"); | 554 | UFSD("EXIT\n"); |
549 | } | 555 | } |
550 | 556 | ||
@@ -572,7 +578,9 @@ static void ufs_put_super_internal(struct super_block *sb) | |||
572 | size = uspi->s_bsize; | 578 | size = uspi->s_bsize; |
573 | if (i + uspi->s_fpb > blks) | 579 | if (i + uspi->s_fpb > blks) |
574 | size = (blks - i) * uspi->s_fsize; | 580 | size = (blks - i) * uspi->s_fsize; |
581 | |||
575 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); | 582 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); |
583 | |||
576 | ubh_memcpyubh (ubh, space, size); | 584 | ubh_memcpyubh (ubh, space, size); |
577 | space += size; | 585 | space += size; |
578 | ubh_mark_buffer_uptodate (ubh, 1); | 586 | ubh_mark_buffer_uptodate (ubh, 1); |
@@ -649,7 +657,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
649 | kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL); | 657 | kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL); |
650 | if (!uspi) | 658 | if (!uspi) |
651 | goto failed; | 659 | goto failed; |
652 | 660 | uspi->s_dirblksize = UFS_SECTOR_SIZE; | |
653 | super_block_offset=UFS_SBLOCK; | 661 | super_block_offset=UFS_SBLOCK; |
654 | 662 | ||
655 | /* Keep 2Gig file limit. Some UFS variants need to override | 663 | /* Keep 2Gig file limit. Some UFS variants need to override |
@@ -674,10 +682,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
674 | uspi->s_sbsize = super_block_size = 1536; | 682 | uspi->s_sbsize = super_block_size = 1536; |
675 | uspi->s_sbbase = 0; | 683 | uspi->s_sbbase = 0; |
676 | flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; | 684 | flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; |
677 | if (!(sb->s_flags & MS_RDONLY)) { | ||
678 | printk(KERN_INFO "ufstype=ufs2 is supported read-only\n"); | ||
679 | sb->s_flags |= MS_RDONLY; | ||
680 | } | ||
681 | break; | 685 | break; |
682 | 686 | ||
683 | case UFS_MOUNT_UFSTYPE_SUN: | 687 | case UFS_MOUNT_UFSTYPE_SUN: |
@@ -718,6 +722,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
718 | break; | 722 | break; |
719 | 723 | ||
720 | case UFS_MOUNT_UFSTYPE_NEXTSTEP: | 724 | case UFS_MOUNT_UFSTYPE_NEXTSTEP: |
725 | /*TODO: check may be we need set special dir block size?*/ | ||
721 | UFSD("ufstype=nextstep\n"); | 726 | UFSD("ufstype=nextstep\n"); |
722 | uspi->s_fsize = block_size = 1024; | 727 | uspi->s_fsize = block_size = 1024; |
723 | uspi->s_fmask = ~(1024 - 1); | 728 | uspi->s_fmask = ~(1024 - 1); |
@@ -733,6 +738,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
733 | break; | 738 | break; |
734 | 739 | ||
735 | case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD: | 740 | case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD: |
741 | /*TODO: check may be we need set special dir block size?*/ | ||
736 | UFSD("ufstype=nextstep-cd\n"); | 742 | UFSD("ufstype=nextstep-cd\n"); |
737 | uspi->s_fsize = block_size = 2048; | 743 | uspi->s_fsize = block_size = 2048; |
738 | uspi->s_fmask = ~(2048 - 1); | 744 | uspi->s_fmask = ~(2048 - 1); |
@@ -754,6 +760,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
754 | uspi->s_fshift = 10; | 760 | uspi->s_fshift = 10; |
755 | uspi->s_sbsize = super_block_size = 2048; | 761 | uspi->s_sbsize = super_block_size = 2048; |
756 | uspi->s_sbbase = 0; | 762 | uspi->s_sbbase = 0; |
763 | uspi->s_dirblksize = 1024; | ||
757 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; | 764 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; |
758 | if (!(sb->s_flags & MS_RDONLY)) { | 765 | if (!(sb->s_flags & MS_RDONLY)) { |
759 | if (!silent) | 766 | if (!silent) |
@@ -887,7 +894,7 @@ magic_found: | |||
887 | } | 894 | } |
888 | 895 | ||
889 | 896 | ||
890 | ufs_print_super_stuff(sb, flags, usb1, usb2, usb3); | 897 | ufs_print_super_stuff(sb, usb1, usb2, usb3); |
891 | 898 | ||
892 | /* | 899 | /* |
893 | * Check, if file system was correctly unmounted. | 900 | * Check, if file system was correctly unmounted. |
@@ -970,7 +977,12 @@ magic_found: | |||
970 | uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3); | 977 | uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3); |
971 | uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave); | 978 | uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave); |
972 | uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew); | 979 | uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew); |
973 | uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr); | 980 | |
981 | if (uspi->fs_magic == UFS2_MAGIC) | ||
982 | uspi->s_csaddr = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr); | ||
983 | else | ||
984 | uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr); | ||
985 | |||
974 | uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize); | 986 | uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize); |
975 | uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize); | 987 | uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize); |
976 | uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak); | 988 | uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak); |
@@ -1057,7 +1069,6 @@ static void ufs_write_super(struct super_block *sb) | |||
1057 | unsigned flags; | 1069 | unsigned flags; |
1058 | 1070 | ||
1059 | lock_kernel(); | 1071 | lock_kernel(); |
1060 | |||
1061 | UFSD("ENTER\n"); | 1072 | UFSD("ENTER\n"); |
1062 | flags = UFS_SB(sb)->s_flags; | 1073 | flags = UFS_SB(sb)->s_flags; |
1063 | uspi = UFS_SB(sb)->s_uspi; | 1074 | uspi = UFS_SB(sb)->s_uspi; |
@@ -1153,7 +1164,8 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
1153 | #else | 1164 | #else |
1154 | if (ufstype != UFS_MOUNT_UFSTYPE_SUN && | 1165 | if (ufstype != UFS_MOUNT_UFSTYPE_SUN && |
1155 | ufstype != UFS_MOUNT_UFSTYPE_44BSD && | 1166 | ufstype != UFS_MOUNT_UFSTYPE_44BSD && |
1156 | ufstype != UFS_MOUNT_UFSTYPE_SUNx86) { | 1167 | ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && |
1168 | ufstype != UFS_MOUNT_UFSTYPE_UFS2) { | ||
1157 | printk("this ufstype is read-only supported\n"); | 1169 | printk("this ufstype is read-only supported\n"); |
1158 | return -EINVAL; | 1170 | return -EINVAL; |
1159 | } | 1171 | } |
@@ -1252,7 +1264,7 @@ static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t); | |||
1252 | static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t); | 1264 | static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t); |
1253 | #endif | 1265 | #endif |
1254 | 1266 | ||
1255 | static struct super_operations ufs_super_ops = { | 1267 | static const struct super_operations ufs_super_ops = { |
1256 | .alloc_inode = ufs_alloc_inode, | 1268 | .alloc_inode = ufs_alloc_inode, |
1257 | .destroy_inode = ufs_destroy_inode, | 1269 | .destroy_inode = ufs_destroy_inode, |
1258 | .read_inode = ufs_read_inode, | 1270 | .read_inode = ufs_read_inode, |
diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c index 337512ed5781..d8549f807e80 100644 --- a/fs/ufs/symlink.c +++ b/fs/ufs/symlink.c | |||
@@ -36,7 +36,7 @@ static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
36 | return NULL; | 36 | return NULL; |
37 | } | 37 | } |
38 | 38 | ||
39 | struct inode_operations ufs_fast_symlink_inode_operations = { | 39 | const struct inode_operations ufs_fast_symlink_inode_operations = { |
40 | .readlink = generic_readlink, | 40 | .readlink = generic_readlink, |
41 | .follow_link = ufs_follow_link, | 41 | .follow_link = ufs_follow_link, |
42 | }; | 42 | }; |
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 0437b0a6fe97..749581fa7729 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c | |||
@@ -30,8 +30,8 @@ | |||
30 | */ | 30 | */ |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * Modified to avoid infinite loop on 2006 by | 33 | * Adoptation to use page cache and UFS2 write support by |
34 | * Evgeniy Dushistov <dushistov@mail.ru> | 34 | * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007 |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <linux/errno.h> | 37 | #include <linux/errno.h> |
@@ -63,13 +63,13 @@ | |||
63 | #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) | 63 | #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) |
64 | 64 | ||
65 | 65 | ||
66 | static int ufs_trunc_direct (struct inode * inode) | 66 | static int ufs_trunc_direct(struct inode *inode) |
67 | { | 67 | { |
68 | struct ufs_inode_info *ufsi = UFS_I(inode); | 68 | struct ufs_inode_info *ufsi = UFS_I(inode); |
69 | struct super_block * sb; | 69 | struct super_block * sb; |
70 | struct ufs_sb_private_info * uspi; | 70 | struct ufs_sb_private_info * uspi; |
71 | __fs32 * p; | 71 | void *p; |
72 | unsigned frag1, frag2, frag3, frag4, block1, block2; | 72 | u64 frag1, frag2, frag3, frag4, block1, block2; |
73 | unsigned frag_to_free, free_count; | 73 | unsigned frag_to_free, free_count; |
74 | unsigned i, tmp; | 74 | unsigned i, tmp; |
75 | int retry; | 75 | int retry; |
@@ -91,13 +91,16 @@ static int ufs_trunc_direct (struct inode * inode) | |||
91 | if (frag2 > frag3) { | 91 | if (frag2 > frag3) { |
92 | frag2 = frag4; | 92 | frag2 = frag4; |
93 | frag3 = frag4 = 0; | 93 | frag3 = frag4 = 0; |
94 | } | 94 | } else if (frag2 < frag3) { |
95 | else if (frag2 < frag3) { | ||
96 | block1 = ufs_fragstoblks (frag2); | 95 | block1 = ufs_fragstoblks (frag2); |
97 | block2 = ufs_fragstoblks (frag3); | 96 | block2 = ufs_fragstoblks (frag3); |
98 | } | 97 | } |
99 | 98 | ||
100 | UFSD("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4); | 99 | UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu," |
100 | " frag4 %llu\n", | ||
101 | (unsigned long long)frag1, (unsigned long long)frag2, | ||
102 | (unsigned long long)block1, (unsigned long long)block2, | ||
103 | (unsigned long long)frag3, (unsigned long long)frag4); | ||
101 | 104 | ||
102 | if (frag1 >= frag2) | 105 | if (frag1 >= frag2) |
103 | goto next1; | 106 | goto next1; |
@@ -105,8 +108,8 @@ static int ufs_trunc_direct (struct inode * inode) | |||
105 | /* | 108 | /* |
106 | * Free first free fragments | 109 | * Free first free fragments |
107 | */ | 110 | */ |
108 | p = ufsi->i_u1.i_data + ufs_fragstoblks (frag1); | 111 | p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1)); |
109 | tmp = fs32_to_cpu(sb, *p); | 112 | tmp = ufs_data_ptr_to_cpu(sb, p); |
110 | if (!tmp ) | 113 | if (!tmp ) |
111 | ufs_panic (sb, "ufs_trunc_direct", "internal error"); | 114 | ufs_panic (sb, "ufs_trunc_direct", "internal error"); |
112 | frag2 -= frag1; | 115 | frag2 -= frag1; |
@@ -121,12 +124,11 @@ next1: | |||
121 | * Free whole blocks | 124 | * Free whole blocks |
122 | */ | 125 | */ |
123 | for (i = block1 ; i < block2; i++) { | 126 | for (i = block1 ; i < block2; i++) { |
124 | p = ufsi->i_u1.i_data + i; | 127 | p = ufs_get_direct_data_ptr(uspi, ufsi, i); |
125 | tmp = fs32_to_cpu(sb, *p); | 128 | tmp = ufs_data_ptr_to_cpu(sb, p); |
126 | if (!tmp) | 129 | if (!tmp) |
127 | continue; | 130 | continue; |
128 | 131 | ufs_data_ptr_clear(uspi, p); | |
129 | *p = 0; | ||
130 | 132 | ||
131 | if (free_count == 0) { | 133 | if (free_count == 0) { |
132 | frag_to_free = tmp; | 134 | frag_to_free = tmp; |
@@ -150,13 +152,12 @@ next1: | |||
150 | /* | 152 | /* |
151 | * Free last free fragments | 153 | * Free last free fragments |
152 | */ | 154 | */ |
153 | p = ufsi->i_u1.i_data + ufs_fragstoblks (frag3); | 155 | p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3)); |
154 | tmp = fs32_to_cpu(sb, *p); | 156 | tmp = ufs_data_ptr_to_cpu(sb, p); |
155 | if (!tmp ) | 157 | if (!tmp ) |
156 | ufs_panic(sb, "ufs_truncate_direct", "internal error"); | 158 | ufs_panic(sb, "ufs_truncate_direct", "internal error"); |
157 | frag4 = ufs_fragnum (frag4); | 159 | frag4 = ufs_fragnum (frag4); |
158 | 160 | ufs_data_ptr_clear(uspi, p); | |
159 | *p = 0; | ||
160 | 161 | ||
161 | ufs_free_fragments (inode, tmp, frag4); | 162 | ufs_free_fragments (inode, tmp, frag4); |
162 | mark_inode_dirty(inode); | 163 | mark_inode_dirty(inode); |
@@ -167,17 +168,20 @@ next1: | |||
167 | } | 168 | } |
168 | 169 | ||
169 | 170 | ||
170 | static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) | 171 | static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p) |
171 | { | 172 | { |
172 | struct super_block * sb; | 173 | struct super_block * sb; |
173 | struct ufs_sb_private_info * uspi; | 174 | struct ufs_sb_private_info * uspi; |
174 | struct ufs_buffer_head * ind_ubh; | 175 | struct ufs_buffer_head * ind_ubh; |
175 | __fs32 * ind; | 176 | void *ind; |
176 | unsigned indirect_block, i, tmp; | 177 | u64 tmp, indirect_block, i, frag_to_free; |
177 | unsigned frag_to_free, free_count; | 178 | unsigned free_count; |
178 | int retry; | 179 | int retry; |
179 | 180 | ||
180 | UFSD("ENTER\n"); | 181 | UFSD("ENTER: ino %lu, offset %llu, p: %p\n", |
182 | inode->i_ino, (unsigned long long)offset, p); | ||
183 | |||
184 | BUG_ON(!p); | ||
181 | 185 | ||
182 | sb = inode->i_sb; | 186 | sb = inode->i_sb; |
183 | uspi = UFS_SB(sb)->s_uspi; | 187 | uspi = UFS_SB(sb)->s_uspi; |
@@ -186,27 +190,27 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) | |||
186 | free_count = 0; | 190 | free_count = 0; |
187 | retry = 0; | 191 | retry = 0; |
188 | 192 | ||
189 | tmp = fs32_to_cpu(sb, *p); | 193 | tmp = ufs_data_ptr_to_cpu(sb, p); |
190 | if (!tmp) | 194 | if (!tmp) |
191 | return 0; | 195 | return 0; |
192 | ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); | 196 | ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); |
193 | if (tmp != fs32_to_cpu(sb, *p)) { | 197 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { |
194 | ubh_brelse (ind_ubh); | 198 | ubh_brelse (ind_ubh); |
195 | return 1; | 199 | return 1; |
196 | } | 200 | } |
197 | if (!ind_ubh) { | 201 | if (!ind_ubh) { |
198 | *p = 0; | 202 | ufs_data_ptr_clear(uspi, p); |
199 | return 0; | 203 | return 0; |
200 | } | 204 | } |
201 | 205 | ||
202 | indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0; | 206 | indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0; |
203 | for (i = indirect_block; i < uspi->s_apb; i++) { | 207 | for (i = indirect_block; i < uspi->s_apb; i++) { |
204 | ind = ubh_get_addr32 (ind_ubh, i); | 208 | ind = ubh_get_data_ptr(uspi, ind_ubh, i); |
205 | tmp = fs32_to_cpu(sb, *ind); | 209 | tmp = ufs_data_ptr_to_cpu(sb, ind); |
206 | if (!tmp) | 210 | if (!tmp) |
207 | continue; | 211 | continue; |
208 | 212 | ||
209 | *ind = 0; | 213 | ufs_data_ptr_clear(uspi, ind); |
210 | ubh_mark_buffer_dirty(ind_ubh); | 214 | ubh_mark_buffer_dirty(ind_ubh); |
211 | if (free_count == 0) { | 215 | if (free_count == 0) { |
212 | frag_to_free = tmp; | 216 | frag_to_free = tmp; |
@@ -226,11 +230,12 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) | |||
226 | ufs_free_blocks (inode, frag_to_free, free_count); | 230 | ufs_free_blocks (inode, frag_to_free, free_count); |
227 | } | 231 | } |
228 | for (i = 0; i < uspi->s_apb; i++) | 232 | for (i = 0; i < uspi->s_apb; i++) |
229 | if (*ubh_get_addr32(ind_ubh,i)) | 233 | if (!ufs_is_data_ptr_zero(uspi, |
234 | ubh_get_data_ptr(uspi, ind_ubh, i))) | ||
230 | break; | 235 | break; |
231 | if (i >= uspi->s_apb) { | 236 | if (i >= uspi->s_apb) { |
232 | tmp = fs32_to_cpu(sb, *p); | 237 | tmp = ufs_data_ptr_to_cpu(sb, p); |
233 | *p = 0; | 238 | ufs_data_ptr_clear(uspi, p); |
234 | 239 | ||
235 | ufs_free_blocks (inode, tmp, uspi->s_fpb); | 240 | ufs_free_blocks (inode, tmp, uspi->s_fpb); |
236 | mark_inode_dirty(inode); | 241 | mark_inode_dirty(inode); |
@@ -248,13 +253,13 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) | |||
248 | return retry; | 253 | return retry; |
249 | } | 254 | } |
250 | 255 | ||
251 | static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) | 256 | static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) |
252 | { | 257 | { |
253 | struct super_block * sb; | 258 | struct super_block * sb; |
254 | struct ufs_sb_private_info * uspi; | 259 | struct ufs_sb_private_info * uspi; |
255 | struct ufs_buffer_head * dind_bh; | 260 | struct ufs_buffer_head *dind_bh; |
256 | unsigned i, tmp, dindirect_block; | 261 | u64 i, tmp, dindirect_block; |
257 | __fs32 * dind; | 262 | void *dind; |
258 | int retry = 0; | 263 | int retry = 0; |
259 | 264 | ||
260 | UFSD("ENTER\n"); | 265 | UFSD("ENTER\n"); |
@@ -266,22 +271,22 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) | |||
266 | ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; | 271 | ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; |
267 | retry = 0; | 272 | retry = 0; |
268 | 273 | ||
269 | tmp = fs32_to_cpu(sb, *p); | 274 | tmp = ufs_data_ptr_to_cpu(sb, p); |
270 | if (!tmp) | 275 | if (!tmp) |
271 | return 0; | 276 | return 0; |
272 | dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); | 277 | dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); |
273 | if (tmp != fs32_to_cpu(sb, *p)) { | 278 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { |
274 | ubh_brelse (dind_bh); | 279 | ubh_brelse (dind_bh); |
275 | return 1; | 280 | return 1; |
276 | } | 281 | } |
277 | if (!dind_bh) { | 282 | if (!dind_bh) { |
278 | *p = 0; | 283 | ufs_data_ptr_clear(uspi, p); |
279 | return 0; | 284 | return 0; |
280 | } | 285 | } |
281 | 286 | ||
282 | for (i = dindirect_block ; i < uspi->s_apb ; i++) { | 287 | for (i = dindirect_block ; i < uspi->s_apb ; i++) { |
283 | dind = ubh_get_addr32 (dind_bh, i); | 288 | dind = ubh_get_data_ptr(uspi, dind_bh, i); |
284 | tmp = fs32_to_cpu(sb, *dind); | 289 | tmp = ufs_data_ptr_to_cpu(sb, dind); |
285 | if (!tmp) | 290 | if (!tmp) |
286 | continue; | 291 | continue; |
287 | retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); | 292 | retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); |
@@ -289,11 +294,12 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) | |||
289 | } | 294 | } |
290 | 295 | ||
291 | for (i = 0; i < uspi->s_apb; i++) | 296 | for (i = 0; i < uspi->s_apb; i++) |
292 | if (*ubh_get_addr32 (dind_bh, i)) | 297 | if (!ufs_is_data_ptr_zero(uspi, |
298 | ubh_get_data_ptr(uspi, dind_bh, i))) | ||
293 | break; | 299 | break; |
294 | if (i >= uspi->s_apb) { | 300 | if (i >= uspi->s_apb) { |
295 | tmp = fs32_to_cpu(sb, *p); | 301 | tmp = ufs_data_ptr_to_cpu(sb, p); |
296 | *p = 0; | 302 | ufs_data_ptr_clear(uspi, p); |
297 | 303 | ||
298 | ufs_free_blocks(inode, tmp, uspi->s_fpb); | 304 | ufs_free_blocks(inode, tmp, uspi->s_fpb); |
299 | mark_inode_dirty(inode); | 305 | mark_inode_dirty(inode); |
@@ -311,34 +317,33 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) | |||
311 | return retry; | 317 | return retry; |
312 | } | 318 | } |
313 | 319 | ||
314 | static int ufs_trunc_tindirect (struct inode * inode) | 320 | static int ufs_trunc_tindirect(struct inode *inode) |
315 | { | 321 | { |
322 | struct super_block *sb = inode->i_sb; | ||
323 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
316 | struct ufs_inode_info *ufsi = UFS_I(inode); | 324 | struct ufs_inode_info *ufsi = UFS_I(inode); |
317 | struct super_block * sb; | ||
318 | struct ufs_sb_private_info * uspi; | ||
319 | struct ufs_buffer_head * tind_bh; | 325 | struct ufs_buffer_head * tind_bh; |
320 | unsigned tindirect_block, tmp, i; | 326 | u64 tindirect_block, tmp, i; |
321 | __fs32 * tind, * p; | 327 | void *tind, *p; |
322 | int retry; | 328 | int retry; |
323 | 329 | ||
324 | UFSD("ENTER\n"); | 330 | UFSD("ENTER\n"); |
325 | 331 | ||
326 | sb = inode->i_sb; | ||
327 | uspi = UFS_SB(sb)->s_uspi; | ||
328 | retry = 0; | 332 | retry = 0; |
329 | 333 | ||
330 | tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) | 334 | tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) |
331 | ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; | 335 | ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; |
332 | p = ufsi->i_u1.i_data + UFS_TIND_BLOCK; | 336 | |
333 | if (!(tmp = fs32_to_cpu(sb, *p))) | 337 | p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK); |
338 | if (!(tmp = ufs_data_ptr_to_cpu(sb, p))) | ||
334 | return 0; | 339 | return 0; |
335 | tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); | 340 | tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); |
336 | if (tmp != fs32_to_cpu(sb, *p)) { | 341 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { |
337 | ubh_brelse (tind_bh); | 342 | ubh_brelse (tind_bh); |
338 | return 1; | 343 | return 1; |
339 | } | 344 | } |
340 | if (!tind_bh) { | 345 | if (!tind_bh) { |
341 | *p = 0; | 346 | ufs_data_ptr_clear(uspi, p); |
342 | return 0; | 347 | return 0; |
343 | } | 348 | } |
344 | 349 | ||
@@ -349,11 +354,12 @@ static int ufs_trunc_tindirect (struct inode * inode) | |||
349 | ubh_mark_buffer_dirty(tind_bh); | 354 | ubh_mark_buffer_dirty(tind_bh); |
350 | } | 355 | } |
351 | for (i = 0; i < uspi->s_apb; i++) | 356 | for (i = 0; i < uspi->s_apb; i++) |
352 | if (*ubh_get_addr32 (tind_bh, i)) | 357 | if (!ufs_is_data_ptr_zero(uspi, |
358 | ubh_get_data_ptr(uspi, tind_bh, i))) | ||
353 | break; | 359 | break; |
354 | if (i >= uspi->s_apb) { | 360 | if (i >= uspi->s_apb) { |
355 | tmp = fs32_to_cpu(sb, *p); | 361 | tmp = ufs_data_ptr_to_cpu(sb, p); |
356 | *p = 0; | 362 | ufs_data_ptr_clear(uspi, p); |
357 | 363 | ||
358 | ufs_free_blocks(inode, tmp, uspi->s_fpb); | 364 | ufs_free_blocks(inode, tmp, uspi->s_fpb); |
359 | mark_inode_dirty(inode); | 365 | mark_inode_dirty(inode); |
@@ -375,7 +381,8 @@ static int ufs_alloc_lastblock(struct inode *inode) | |||
375 | int err = 0; | 381 | int err = 0; |
376 | struct address_space *mapping = inode->i_mapping; | 382 | struct address_space *mapping = inode->i_mapping; |
377 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; | 383 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; |
378 | unsigned lastfrag, i, end; | 384 | unsigned i, end; |
385 | sector_t lastfrag; | ||
379 | struct page *lastpage; | 386 | struct page *lastpage; |
380 | struct buffer_head *bh; | 387 | struct buffer_head *bh; |
381 | 388 | ||
@@ -430,7 +437,9 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) | |||
430 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 437 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
431 | int retry, err = 0; | 438 | int retry, err = 0; |
432 | 439 | ||
433 | UFSD("ENTER\n"); | 440 | UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n", |
441 | inode->i_ino, (unsigned long long)i_size_read(inode), | ||
442 | (unsigned long long)old_i_size); | ||
434 | 443 | ||
435 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 444 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
436 | S_ISLNK(inode->i_mode))) | 445 | S_ISLNK(inode->i_mode))) |
@@ -450,10 +459,12 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) | |||
450 | lock_kernel(); | 459 | lock_kernel(); |
451 | while (1) { | 460 | while (1) { |
452 | retry = ufs_trunc_direct(inode); | 461 | retry = ufs_trunc_direct(inode); |
453 | retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK, | 462 | retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK, |
454 | (__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]); | 463 | ufs_get_direct_data_ptr(uspi, ufsi, |
455 | retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb, | 464 | UFS_IND_BLOCK)); |
456 | (__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]); | 465 | retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb, |
466 | ufs_get_direct_data_ptr(uspi, ufsi, | ||
467 | UFS_DIND_BLOCK)); | ||
457 | retry |= ufs_trunc_tindirect (inode); | 468 | retry |= ufs_trunc_tindirect (inode); |
458 | if (!retry) | 469 | if (!retry) |
459 | break; | 470 | break; |
@@ -502,6 +513,6 @@ static int ufs_setattr(struct dentry *dentry, struct iattr *attr) | |||
502 | return inode_setattr(inode, attr); | 513 | return inode_setattr(inode, attr); |
503 | } | 514 | } |
504 | 515 | ||
505 | struct inode_operations ufs_file_inode_operations = { | 516 | const struct inode_operations ufs_file_inode_operations = { |
506 | .setattr = ufs_setattr, | 517 | .setattr = ufs_setattr, |
507 | }; | 518 | }; |
diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 7dd12bb1d62b..06d344839c42 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h | |||
@@ -305,8 +305,22 @@ static inline void *get_usb_offset(struct ufs_sb_private_info *uspi, | |||
305 | (((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \ | 305 | (((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \ |
306 | ((begin) & ((uspi->s_fsize>>2) - 1))) | 306 | ((begin) & ((uspi->s_fsize>>2) - 1))) |
307 | 307 | ||
308 | #define ubh_get_addr64(ubh,begin) \ | ||
309 | (((__fs64*)((ubh)->bh[(begin) >> (uspi->s_fshift-3)]->b_data)) + \ | ||
310 | ((begin) & ((uspi->s_fsize>>3) - 1))) | ||
311 | |||
308 | #define ubh_get_addr ubh_get_addr8 | 312 | #define ubh_get_addr ubh_get_addr8 |
309 | 313 | ||
314 | static inline void *ubh_get_data_ptr(struct ufs_sb_private_info *uspi, | ||
315 | struct ufs_buffer_head *ubh, | ||
316 | u64 blk) | ||
317 | { | ||
318 | if (uspi->fs_magic == UFS2_MAGIC) | ||
319 | return ubh_get_addr64(ubh, blk); | ||
320 | else | ||
321 | return ubh_get_addr32(ubh, blk); | ||
322 | } | ||
323 | |||
310 | #define ubh_blkmap(ubh,begin,bit) \ | 324 | #define ubh_blkmap(ubh,begin,bit) \ |
311 | ((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb))) | 325 | ((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb))) |
312 | 326 | ||
@@ -507,3 +521,46 @@ static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap, | |||
507 | if (fragsize > 0 && fragsize < uspi->s_fpb) | 521 | if (fragsize > 0 && fragsize < uspi->s_fpb) |
508 | fs32_add(sb, &fraglist[fragsize], cnt); | 522 | fs32_add(sb, &fraglist[fragsize], cnt); |
509 | } | 523 | } |
524 | |||
525 | static inline void *ufs_get_direct_data_ptr(struct ufs_sb_private_info *uspi, | ||
526 | struct ufs_inode_info *ufsi, | ||
527 | unsigned blk) | ||
528 | { | ||
529 | BUG_ON(blk > UFS_TIND_BLOCK); | ||
530 | return uspi->fs_magic == UFS2_MAGIC ? | ||
531 | (void *)&ufsi->i_u1.u2_i_data[blk] : | ||
532 | (void *)&ufsi->i_u1.i_data[blk]; | ||
533 | } | ||
534 | |||
535 | static inline u64 ufs_data_ptr_to_cpu(struct super_block *sb, void *p) | ||
536 | { | ||
537 | return UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC ? | ||
538 | fs64_to_cpu(sb, *(__fs64 *)p) : | ||
539 | fs32_to_cpu(sb, *(__fs32 *)p); | ||
540 | } | ||
541 | |||
542 | static inline void ufs_cpu_to_data_ptr(struct super_block *sb, void *p, u64 val) | ||
543 | { | ||
544 | if (UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC) | ||
545 | *(__fs64 *)p = cpu_to_fs64(sb, val); | ||
546 | else | ||
547 | *(__fs32 *)p = cpu_to_fs32(sb, val); | ||
548 | } | ||
549 | |||
550 | static inline void ufs_data_ptr_clear(struct ufs_sb_private_info *uspi, | ||
551 | void *p) | ||
552 | { | ||
553 | if (uspi->fs_magic == UFS2_MAGIC) | ||
554 | *(__fs64 *)p = 0; | ||
555 | else | ||
556 | *(__fs32 *)p = 0; | ||
557 | } | ||
558 | |||
559 | static inline int ufs_is_data_ptr_zero(struct ufs_sb_private_info *uspi, | ||
560 | void *p) | ||
561 | { | ||
562 | if (uspi->fs_magic == UFS2_MAGIC) | ||
563 | return *(__fs64 *)p == 0; | ||
564 | else | ||
565 | return *(__fs32 *)p == 0; | ||
566 | } | ||
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 0afd745a37cd..c28add2fbe95 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c | |||
@@ -996,7 +996,7 @@ error_inode: | |||
996 | goto out; | 996 | goto out; |
997 | } | 997 | } |
998 | 998 | ||
999 | static struct inode_operations vfat_dir_inode_operations = { | 999 | static const struct inode_operations vfat_dir_inode_operations = { |
1000 | .create = vfat_create, | 1000 | .create = vfat_create, |
1001 | .lookup = vfat_lookup, | 1001 | .lookup = vfat_lookup, |
1002 | .unlink = vfat_unlink, | 1002 | .unlink = vfat_unlink, |
diff --git a/fs/xattr_acl.c b/fs/xattr_acl.c index 789a2559bd54..c6ad7c7e3ee9 100644 --- a/fs/xattr_acl.c +++ b/fs/xattr_acl.c | |||
@@ -6,7 +6,6 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/sched.h> | ||
10 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
11 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
12 | #include <linux/posix_acl_xattr.h> | 11 | #include <linux/posix_acl_xattr.h> |
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 004baf600611..ed2b16dff914 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * along with this program; if not, write the Free Software Foundation, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include <linux/sched.h> | ||
19 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
20 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
21 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h index 32e1ce0f04c9..af168a1a98c1 100644 --- a/fs/xfs/linux-2.6/mrlock.h +++ b/fs/xfs/linux-2.6/mrlock.h | |||
@@ -31,15 +31,13 @@ typedef struct { | |||
31 | do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0) | 31 | do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0) |
32 | #define mrlock_init(mrp, t,n,s) mrinit(mrp, n) | 32 | #define mrlock_init(mrp, t,n,s) mrinit(mrp, n) |
33 | #define mrfree(mrp) do { } while (0) | 33 | #define mrfree(mrp) do { } while (0) |
34 | #define mraccess(mrp) mraccessf(mrp, 0) | ||
35 | #define mrupdate(mrp) mrupdatef(mrp, 0) | ||
36 | 34 | ||
37 | static inline void mraccessf(mrlock_t *mrp, int flags) | 35 | static inline void mraccess(mrlock_t *mrp) |
38 | { | 36 | { |
39 | down_read(&mrp->mr_lock); | 37 | down_read(&mrp->mr_lock); |
40 | } | 38 | } |
41 | 39 | ||
42 | static inline void mrupdatef(mrlock_t *mrp, int flags) | 40 | static inline void mrupdate(mrlock_t *mrp) |
43 | { | 41 | { |
44 | down_write(&mrp->mr_lock); | 42 | down_write(&mrp->mr_lock); |
45 | mrp->mr_writer = 1; | 43 | mrp->mr_writer = 1; |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 7b54461695e2..143ffc851c9d 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -56,8 +56,6 @@ xfs_count_page_state( | |||
56 | do { | 56 | do { |
57 | if (buffer_uptodate(bh) && !buffer_mapped(bh)) | 57 | if (buffer_uptodate(bh) && !buffer_mapped(bh)) |
58 | (*unmapped) = 1; | 58 | (*unmapped) = 1; |
59 | else if (buffer_unwritten(bh) && !buffer_delay(bh)) | ||
60 | clear_buffer_unwritten(bh); | ||
61 | else if (buffer_unwritten(bh)) | 59 | else if (buffer_unwritten(bh)) |
62 | (*unwritten) = 1; | 60 | (*unwritten) = 1; |
63 | else if (buffer_delay(bh)) | 61 | else if (buffer_delay(bh)) |
@@ -249,7 +247,7 @@ xfs_map_blocks( | |||
249 | return -error; | 247 | return -error; |
250 | } | 248 | } |
251 | 249 | ||
252 | STATIC inline int | 250 | STATIC_INLINE int |
253 | xfs_iomap_valid( | 251 | xfs_iomap_valid( |
254 | xfs_iomap_t *iomapp, | 252 | xfs_iomap_t *iomapp, |
255 | loff_t offset) | 253 | loff_t offset) |
@@ -1272,7 +1270,6 @@ __xfs_get_blocks( | |||
1272 | if (direct) | 1270 | if (direct) |
1273 | bh_result->b_private = inode; | 1271 | bh_result->b_private = inode; |
1274 | set_buffer_unwritten(bh_result); | 1272 | set_buffer_unwritten(bh_result); |
1275 | set_buffer_delay(bh_result); | ||
1276 | } | 1273 | } |
1277 | } | 1274 | } |
1278 | 1275 | ||
@@ -1283,13 +1280,18 @@ __xfs_get_blocks( | |||
1283 | bh_result->b_bdev = iomap.iomap_target->bt_bdev; | 1280 | bh_result->b_bdev = iomap.iomap_target->bt_bdev; |
1284 | 1281 | ||
1285 | /* | 1282 | /* |
1286 | * If we previously allocated a block out beyond eof and we are | 1283 | * If we previously allocated a block out beyond eof and we are now |
1287 | * now coming back to use it then we will need to flag it as new | 1284 | * coming back to use it then we will need to flag it as new even if it |
1288 | * even if it has a disk address. | 1285 | * has a disk address. |
1286 | * | ||
1287 | * With sub-block writes into unwritten extents we also need to mark | ||
1288 | * the buffer as new so that the unwritten parts of the buffer gets | ||
1289 | * correctly zeroed. | ||
1289 | */ | 1290 | */ |
1290 | if (create && | 1291 | if (create && |
1291 | ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) || | 1292 | ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) || |
1292 | (offset >= i_size_read(inode)) || (iomap.iomap_flags & IOMAP_NEW))) | 1293 | (offset >= i_size_read(inode)) || |
1294 | (iomap.iomap_flags & (IOMAP_NEW|IOMAP_UNWRITTEN)))) | ||
1293 | set_buffer_new(bh_result); | 1295 | set_buffer_new(bh_result); |
1294 | 1296 | ||
1295 | if (iomap.iomap_flags & IOMAP_DELAY) { | 1297 | if (iomap.iomap_flags & IOMAP_DELAY) { |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 4fb01ffdfd1a..e2bea6a661f0 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -34,13 +34,13 @@ | |||
34 | #include <linux/backing-dev.h> | 34 | #include <linux/backing-dev.h> |
35 | #include <linux/freezer.h> | 35 | #include <linux/freezer.h> |
36 | 36 | ||
37 | STATIC kmem_zone_t *xfs_buf_zone; | 37 | static kmem_zone_t *xfs_buf_zone; |
38 | STATIC kmem_shaker_t xfs_buf_shake; | 38 | static kmem_shaker_t xfs_buf_shake; |
39 | STATIC int xfsbufd(void *); | 39 | STATIC int xfsbufd(void *); |
40 | STATIC int xfsbufd_wakeup(int, gfp_t); | 40 | STATIC int xfsbufd_wakeup(int, gfp_t); |
41 | STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int); | 41 | STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int); |
42 | 42 | ||
43 | STATIC struct workqueue_struct *xfslogd_workqueue; | 43 | static struct workqueue_struct *xfslogd_workqueue; |
44 | struct workqueue_struct *xfsdatad_workqueue; | 44 | struct workqueue_struct *xfsdatad_workqueue; |
45 | 45 | ||
46 | #ifdef XFS_BUF_TRACE | 46 | #ifdef XFS_BUF_TRACE |
@@ -139,7 +139,7 @@ page_region_mask( | |||
139 | return mask; | 139 | return mask; |
140 | } | 140 | } |
141 | 141 | ||
142 | STATIC inline void | 142 | STATIC_INLINE void |
143 | set_page_region( | 143 | set_page_region( |
144 | struct page *page, | 144 | struct page *page, |
145 | size_t offset, | 145 | size_t offset, |
@@ -151,7 +151,7 @@ set_page_region( | |||
151 | SetPageUptodate(page); | 151 | SetPageUptodate(page); |
152 | } | 152 | } |
153 | 153 | ||
154 | STATIC inline int | 154 | STATIC_INLINE int |
155 | test_page_region( | 155 | test_page_region( |
156 | struct page *page, | 156 | struct page *page, |
157 | size_t offset, | 157 | size_t offset, |
@@ -171,9 +171,9 @@ typedef struct a_list { | |||
171 | struct a_list *next; | 171 | struct a_list *next; |
172 | } a_list_t; | 172 | } a_list_t; |
173 | 173 | ||
174 | STATIC a_list_t *as_free_head; | 174 | static a_list_t *as_free_head; |
175 | STATIC int as_list_len; | 175 | static int as_list_len; |
176 | STATIC DEFINE_SPINLOCK(as_lock); | 176 | static DEFINE_SPINLOCK(as_lock); |
177 | 177 | ||
178 | /* | 178 | /* |
179 | * Try to batch vunmaps because they are costly. | 179 | * Try to batch vunmaps because they are costly. |
@@ -1085,7 +1085,7 @@ xfs_buf_iostart( | |||
1085 | return status; | 1085 | return status; |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | STATIC __inline__ int | 1088 | STATIC_INLINE int |
1089 | _xfs_buf_iolocked( | 1089 | _xfs_buf_iolocked( |
1090 | xfs_buf_t *bp) | 1090 | xfs_buf_t *bp) |
1091 | { | 1091 | { |
@@ -1095,7 +1095,7 @@ _xfs_buf_iolocked( | |||
1095 | return 0; | 1095 | return 0; |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | STATIC __inline__ void | 1098 | STATIC_INLINE void |
1099 | _xfs_buf_ioend( | 1099 | _xfs_buf_ioend( |
1100 | xfs_buf_t *bp, | 1100 | xfs_buf_t *bp, |
1101 | int schedule) | 1101 | int schedule) |
@@ -1426,8 +1426,8 @@ xfs_free_bufhash( | |||
1426 | /* | 1426 | /* |
1427 | * buftarg list for delwrite queue processing | 1427 | * buftarg list for delwrite queue processing |
1428 | */ | 1428 | */ |
1429 | STATIC LIST_HEAD(xfs_buftarg_list); | 1429 | LIST_HEAD(xfs_buftarg_list); |
1430 | STATIC DEFINE_SPINLOCK(xfs_buftarg_lock); | 1430 | static DEFINE_SPINLOCK(xfs_buftarg_lock); |
1431 | 1431 | ||
1432 | STATIC void | 1432 | STATIC void |
1433 | xfs_register_buftarg( | 1433 | xfs_register_buftarg( |
@@ -1679,21 +1679,60 @@ xfsbufd_wakeup( | |||
1679 | return 0; | 1679 | return 0; |
1680 | } | 1680 | } |
1681 | 1681 | ||
1682 | /* | ||
1683 | * Move as many buffers as specified to the supplied list | ||
1684 | * idicating if we skipped any buffers to prevent deadlocks. | ||
1685 | */ | ||
1686 | STATIC int | ||
1687 | xfs_buf_delwri_split( | ||
1688 | xfs_buftarg_t *target, | ||
1689 | struct list_head *list, | ||
1690 | unsigned long age) | ||
1691 | { | ||
1692 | xfs_buf_t *bp, *n; | ||
1693 | struct list_head *dwq = &target->bt_delwrite_queue; | ||
1694 | spinlock_t *dwlk = &target->bt_delwrite_lock; | ||
1695 | int skipped = 0; | ||
1696 | int force; | ||
1697 | |||
1698 | force = test_and_clear_bit(XBT_FORCE_FLUSH, &target->bt_flags); | ||
1699 | INIT_LIST_HEAD(list); | ||
1700 | spin_lock(dwlk); | ||
1701 | list_for_each_entry_safe(bp, n, dwq, b_list) { | ||
1702 | XB_TRACE(bp, "walkq1", (long)xfs_buf_ispin(bp)); | ||
1703 | ASSERT(bp->b_flags & XBF_DELWRI); | ||
1704 | |||
1705 | if (!xfs_buf_ispin(bp) && !xfs_buf_cond_lock(bp)) { | ||
1706 | if (!force && | ||
1707 | time_before(jiffies, bp->b_queuetime + age)) { | ||
1708 | xfs_buf_unlock(bp); | ||
1709 | break; | ||
1710 | } | ||
1711 | |||
1712 | bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q| | ||
1713 | _XBF_RUN_QUEUES); | ||
1714 | bp->b_flags |= XBF_WRITE; | ||
1715 | list_move_tail(&bp->b_list, list); | ||
1716 | } else | ||
1717 | skipped++; | ||
1718 | } | ||
1719 | spin_unlock(dwlk); | ||
1720 | |||
1721 | return skipped; | ||
1722 | |||
1723 | } | ||
1724 | |||
1682 | STATIC int | 1725 | STATIC int |
1683 | xfsbufd( | 1726 | xfsbufd( |
1684 | void *data) | 1727 | void *data) |
1685 | { | 1728 | { |
1686 | struct list_head tmp; | 1729 | struct list_head tmp; |
1687 | unsigned long age; | 1730 | xfs_buftarg_t *target = (xfs_buftarg_t *)data; |
1688 | xfs_buftarg_t *target = (xfs_buftarg_t *)data; | 1731 | int count; |
1689 | xfs_buf_t *bp, *n; | 1732 | xfs_buf_t *bp; |
1690 | struct list_head *dwq = &target->bt_delwrite_queue; | ||
1691 | spinlock_t *dwlk = &target->bt_delwrite_lock; | ||
1692 | int count; | ||
1693 | 1733 | ||
1694 | current->flags |= PF_MEMALLOC; | 1734 | current->flags |= PF_MEMALLOC; |
1695 | 1735 | ||
1696 | INIT_LIST_HEAD(&tmp); | ||
1697 | do { | 1736 | do { |
1698 | if (unlikely(freezing(current))) { | 1737 | if (unlikely(freezing(current))) { |
1699 | set_bit(XBT_FORCE_SLEEP, &target->bt_flags); | 1738 | set_bit(XBT_FORCE_SLEEP, &target->bt_flags); |
@@ -1705,37 +1744,17 @@ xfsbufd( | |||
1705 | schedule_timeout_interruptible( | 1744 | schedule_timeout_interruptible( |
1706 | xfs_buf_timer_centisecs * msecs_to_jiffies(10)); | 1745 | xfs_buf_timer_centisecs * msecs_to_jiffies(10)); |
1707 | 1746 | ||
1708 | count = 0; | 1747 | xfs_buf_delwri_split(target, &tmp, |
1709 | age = xfs_buf_age_centisecs * msecs_to_jiffies(10); | 1748 | xfs_buf_age_centisecs * msecs_to_jiffies(10)); |
1710 | spin_lock(dwlk); | ||
1711 | list_for_each_entry_safe(bp, n, dwq, b_list) { | ||
1712 | XB_TRACE(bp, "walkq1", (long)xfs_buf_ispin(bp)); | ||
1713 | ASSERT(bp->b_flags & XBF_DELWRI); | ||
1714 | |||
1715 | if (!xfs_buf_ispin(bp) && !xfs_buf_cond_lock(bp)) { | ||
1716 | if (!test_bit(XBT_FORCE_FLUSH, | ||
1717 | &target->bt_flags) && | ||
1718 | time_before(jiffies, | ||
1719 | bp->b_queuetime + age)) { | ||
1720 | xfs_buf_unlock(bp); | ||
1721 | break; | ||
1722 | } | ||
1723 | |||
1724 | bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q| | ||
1725 | _XBF_RUN_QUEUES); | ||
1726 | bp->b_flags |= XBF_WRITE; | ||
1727 | list_move_tail(&bp->b_list, &tmp); | ||
1728 | count++; | ||
1729 | } | ||
1730 | } | ||
1731 | spin_unlock(dwlk); | ||
1732 | 1749 | ||
1750 | count = 0; | ||
1733 | while (!list_empty(&tmp)) { | 1751 | while (!list_empty(&tmp)) { |
1734 | bp = list_entry(tmp.next, xfs_buf_t, b_list); | 1752 | bp = list_entry(tmp.next, xfs_buf_t, b_list); |
1735 | ASSERT(target == bp->b_target); | 1753 | ASSERT(target == bp->b_target); |
1736 | 1754 | ||
1737 | list_del_init(&bp->b_list); | 1755 | list_del_init(&bp->b_list); |
1738 | xfs_buf_iostrategy(bp); | 1756 | xfs_buf_iostrategy(bp); |
1757 | count++; | ||
1739 | } | 1758 | } |
1740 | 1759 | ||
1741 | if (as_list_len > 0) | 1760 | if (as_list_len > 0) |
@@ -1743,7 +1762,6 @@ xfsbufd( | |||
1743 | if (count) | 1762 | if (count) |
1744 | blk_run_address_space(target->bt_mapping); | 1763 | blk_run_address_space(target->bt_mapping); |
1745 | 1764 | ||
1746 | clear_bit(XBT_FORCE_FLUSH, &target->bt_flags); | ||
1747 | } while (!kthread_should_stop()); | 1765 | } while (!kthread_should_stop()); |
1748 | 1766 | ||
1749 | return 0; | 1767 | return 0; |
@@ -1756,40 +1774,24 @@ xfsbufd( | |||
1756 | */ | 1774 | */ |
1757 | int | 1775 | int |
1758 | xfs_flush_buftarg( | 1776 | xfs_flush_buftarg( |
1759 | xfs_buftarg_t *target, | 1777 | xfs_buftarg_t *target, |
1760 | int wait) | 1778 | int wait) |
1761 | { | 1779 | { |
1762 | struct list_head tmp; | 1780 | struct list_head tmp; |
1763 | xfs_buf_t *bp, *n; | 1781 | xfs_buf_t *bp, *n; |
1764 | int pincount = 0; | 1782 | int pincount = 0; |
1765 | struct list_head *dwq = &target->bt_delwrite_queue; | ||
1766 | spinlock_t *dwlk = &target->bt_delwrite_lock; | ||
1767 | 1783 | ||
1768 | xfs_buf_runall_queues(xfsdatad_workqueue); | 1784 | xfs_buf_runall_queues(xfsdatad_workqueue); |
1769 | xfs_buf_runall_queues(xfslogd_workqueue); | 1785 | xfs_buf_runall_queues(xfslogd_workqueue); |
1770 | 1786 | ||
1771 | INIT_LIST_HEAD(&tmp); | 1787 | set_bit(XBT_FORCE_FLUSH, &target->bt_flags); |
1772 | spin_lock(dwlk); | 1788 | pincount = xfs_buf_delwri_split(target, &tmp, 0); |
1773 | list_for_each_entry_safe(bp, n, dwq, b_list) { | ||
1774 | ASSERT(bp->b_target == target); | ||
1775 | ASSERT(bp->b_flags & (XBF_DELWRI | _XBF_DELWRI_Q)); | ||
1776 | XB_TRACE(bp, "walkq2", (long)xfs_buf_ispin(bp)); | ||
1777 | if (xfs_buf_ispin(bp)) { | ||
1778 | pincount++; | ||
1779 | continue; | ||
1780 | } | ||
1781 | |||
1782 | list_move_tail(&bp->b_list, &tmp); | ||
1783 | } | ||
1784 | spin_unlock(dwlk); | ||
1785 | 1789 | ||
1786 | /* | 1790 | /* |
1787 | * Dropped the delayed write list lock, now walk the temporary list | 1791 | * Dropped the delayed write list lock, now walk the temporary list |
1788 | */ | 1792 | */ |
1789 | list_for_each_entry_safe(bp, n, &tmp, b_list) { | 1793 | list_for_each_entry_safe(bp, n, &tmp, b_list) { |
1790 | xfs_buf_lock(bp); | 1794 | ASSERT(target == bp->b_target); |
1791 | bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|_XBF_RUN_QUEUES); | ||
1792 | bp->b_flags |= XBF_WRITE; | ||
1793 | if (wait) | 1795 | if (wait) |
1794 | bp->b_flags &= ~XBF_ASYNC; | 1796 | bp->b_flags &= ~XBF_ASYNC; |
1795 | else | 1797 | else |
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index 9dd235cb0107..9e8ef8fef39f 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h | |||
@@ -69,8 +69,8 @@ typedef enum { | |||
69 | } xfs_buf_flags_t; | 69 | } xfs_buf_flags_t; |
70 | 70 | ||
71 | typedef enum { | 71 | typedef enum { |
72 | XBT_FORCE_SLEEP = (0 << 1), | 72 | XBT_FORCE_SLEEP = 0, |
73 | XBT_FORCE_FLUSH = (1 << 1), | 73 | XBT_FORCE_FLUSH = 1, |
74 | } xfs_buftarg_flags_t; | 74 | } xfs_buftarg_flags_t; |
75 | 75 | ||
76 | typedef struct xfs_bufhash { | 76 | typedef struct xfs_bufhash { |
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 5fb75d9151f2..e3a5fedac1ba 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include "xfs_mount.h" | 24 | #include "xfs_mount.h" |
25 | #include "xfs_export.h" | 25 | #include "xfs_export.h" |
26 | 26 | ||
27 | STATIC struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, }; | 27 | static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, }; |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * XFS encodes and decodes the fileid portion of NFS filehandles | 30 | * XFS encodes and decodes the fileid portion of NFS filehandles |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index d26f5cd2ba70..cb51dc961355 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -46,7 +46,7 @@ static struct vm_operations_struct xfs_file_vm_ops; | |||
46 | static struct vm_operations_struct xfs_dmapi_file_vm_ops; | 46 | static struct vm_operations_struct xfs_dmapi_file_vm_ops; |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | STATIC inline ssize_t | 49 | STATIC_INLINE ssize_t |
50 | __xfs_file_read( | 50 | __xfs_file_read( |
51 | struct kiocb *iocb, | 51 | struct kiocb *iocb, |
52 | const struct iovec *iov, | 52 | const struct iovec *iov, |
@@ -84,7 +84,7 @@ xfs_file_aio_read_invis( | |||
84 | return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos); | 84 | return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos); |
85 | } | 85 | } |
86 | 86 | ||
87 | STATIC inline ssize_t | 87 | STATIC_INLINE ssize_t |
88 | __xfs_file_write( | 88 | __xfs_file_write( |
89 | struct kiocb *iocb, | 89 | struct kiocb *iocb, |
90 | const struct iovec *iov, | 90 | const struct iovec *iov, |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index f011c9cd0d62..ff5c41ff8d40 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -41,8 +41,6 @@ | |||
41 | #include "xfs_error.h" | 41 | #include "xfs_error.h" |
42 | #include "xfs_rw.h" | 42 | #include "xfs_rw.h" |
43 | #include "xfs_acl.h" | 43 | #include "xfs_acl.h" |
44 | #include "xfs_cap.h" | ||
45 | #include "xfs_mac.h" | ||
46 | #include "xfs_attr.h" | 44 | #include "xfs_attr.h" |
47 | #include "xfs_bmap.h" | 45 | #include "xfs_bmap.h" |
48 | #include "xfs_buf_item.h" | 46 | #include "xfs_buf_item.h" |
@@ -355,7 +353,6 @@ STATIC int | |||
355 | xfs_readlink_by_handle( | 353 | xfs_readlink_by_handle( |
356 | xfs_mount_t *mp, | 354 | xfs_mount_t *mp, |
357 | void __user *arg, | 355 | void __user *arg, |
358 | struct file *parfilp, | ||
359 | struct inode *parinode) | 356 | struct inode *parinode) |
360 | { | 357 | { |
361 | int error; | 358 | int error; |
@@ -388,7 +385,7 @@ xfs_readlink_by_handle( | |||
388 | aiov.iov_len = olen; | 385 | aiov.iov_len = olen; |
389 | aiov.iov_base = hreq.ohandle; | 386 | aiov.iov_base = hreq.ohandle; |
390 | 387 | ||
391 | auio.uio_iov = &aiov; | 388 | auio.uio_iov = (struct kvec *)&aiov; |
392 | auio.uio_iovcnt = 1; | 389 | auio.uio_iovcnt = 1; |
393 | auio.uio_offset = 0; | 390 | auio.uio_offset = 0; |
394 | auio.uio_segflg = UIO_USERSPACE; | 391 | auio.uio_segflg = UIO_USERSPACE; |
@@ -406,7 +403,6 @@ STATIC int | |||
406 | xfs_fssetdm_by_handle( | 403 | xfs_fssetdm_by_handle( |
407 | xfs_mount_t *mp, | 404 | xfs_mount_t *mp, |
408 | void __user *arg, | 405 | void __user *arg, |
409 | struct file *parfilp, | ||
410 | struct inode *parinode) | 406 | struct inode *parinode) |
411 | { | 407 | { |
412 | int error; | 408 | int error; |
@@ -448,7 +444,6 @@ STATIC int | |||
448 | xfs_attrlist_by_handle( | 444 | xfs_attrlist_by_handle( |
449 | xfs_mount_t *mp, | 445 | xfs_mount_t *mp, |
450 | void __user *arg, | 446 | void __user *arg, |
451 | struct file *parfilp, | ||
452 | struct inode *parinode) | 447 | struct inode *parinode) |
453 | { | 448 | { |
454 | int error; | 449 | int error; |
@@ -569,7 +564,6 @@ STATIC int | |||
569 | xfs_attrmulti_by_handle( | 564 | xfs_attrmulti_by_handle( |
570 | xfs_mount_t *mp, | 565 | xfs_mount_t *mp, |
571 | void __user *arg, | 566 | void __user *arg, |
572 | struct file *parfilp, | ||
573 | struct inode *parinode) | 567 | struct inode *parinode) |
574 | { | 568 | { |
575 | int error; | 569 | int error; |
@@ -689,7 +683,6 @@ xfs_ioc_xattr( | |||
689 | STATIC int | 683 | STATIC int |
690 | xfs_ioc_getbmap( | 684 | xfs_ioc_getbmap( |
691 | bhv_desc_t *bdp, | 685 | bhv_desc_t *bdp, |
692 | struct file *filp, | ||
693 | int flags, | 686 | int flags, |
694 | unsigned int cmd, | 687 | unsigned int cmd, |
695 | void __user *arg); | 688 | void __user *arg); |
@@ -788,7 +781,7 @@ xfs_ioctl( | |||
788 | 781 | ||
789 | case XFS_IOC_GETBMAP: | 782 | case XFS_IOC_GETBMAP: |
790 | case XFS_IOC_GETBMAPA: | 783 | case XFS_IOC_GETBMAPA: |
791 | return xfs_ioc_getbmap(bdp, filp, ioflags, cmd, arg); | 784 | return xfs_ioc_getbmap(bdp, ioflags, cmd, arg); |
792 | 785 | ||
793 | case XFS_IOC_GETBMAPX: | 786 | case XFS_IOC_GETBMAPX: |
794 | return xfs_ioc_getbmapx(bdp, arg); | 787 | return xfs_ioc_getbmapx(bdp, arg); |
@@ -802,16 +795,16 @@ xfs_ioctl( | |||
802 | return xfs_open_by_handle(mp, arg, filp, inode); | 795 | return xfs_open_by_handle(mp, arg, filp, inode); |
803 | 796 | ||
804 | case XFS_IOC_FSSETDM_BY_HANDLE: | 797 | case XFS_IOC_FSSETDM_BY_HANDLE: |
805 | return xfs_fssetdm_by_handle(mp, arg, filp, inode); | 798 | return xfs_fssetdm_by_handle(mp, arg, inode); |
806 | 799 | ||
807 | case XFS_IOC_READLINK_BY_HANDLE: | 800 | case XFS_IOC_READLINK_BY_HANDLE: |
808 | return xfs_readlink_by_handle(mp, arg, filp, inode); | 801 | return xfs_readlink_by_handle(mp, arg, inode); |
809 | 802 | ||
810 | case XFS_IOC_ATTRLIST_BY_HANDLE: | 803 | case XFS_IOC_ATTRLIST_BY_HANDLE: |
811 | return xfs_attrlist_by_handle(mp, arg, filp, inode); | 804 | return xfs_attrlist_by_handle(mp, arg, inode); |
812 | 805 | ||
813 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | 806 | case XFS_IOC_ATTRMULTI_BY_HANDLE: |
814 | return xfs_attrmulti_by_handle(mp, arg, filp, inode); | 807 | return xfs_attrmulti_by_handle(mp, arg, inode); |
815 | 808 | ||
816 | case XFS_IOC_SWAPEXT: { | 809 | case XFS_IOC_SWAPEXT: { |
817 | error = xfs_swapext((struct xfs_swapext __user *)arg); | 810 | error = xfs_swapext((struct xfs_swapext __user *)arg); |
@@ -1095,11 +1088,6 @@ xfs_ioc_fsgeometry( | |||
1095 | /* | 1088 | /* |
1096 | * Linux extended inode flags interface. | 1089 | * Linux extended inode flags interface. |
1097 | */ | 1090 | */ |
1098 | #define LINUX_XFLAG_SYNC 0x00000008 /* Synchronous updates */ | ||
1099 | #define LINUX_XFLAG_IMMUTABLE 0x00000010 /* Immutable file */ | ||
1100 | #define LINUX_XFLAG_APPEND 0x00000020 /* writes to file may only append */ | ||
1101 | #define LINUX_XFLAG_NODUMP 0x00000040 /* do not dump file */ | ||
1102 | #define LINUX_XFLAG_NOATIME 0x00000080 /* do not update atime */ | ||
1103 | 1091 | ||
1104 | STATIC unsigned int | 1092 | STATIC unsigned int |
1105 | xfs_merge_ioc_xflags( | 1093 | xfs_merge_ioc_xflags( |
@@ -1108,23 +1096,23 @@ xfs_merge_ioc_xflags( | |||
1108 | { | 1096 | { |
1109 | unsigned int xflags = start; | 1097 | unsigned int xflags = start; |
1110 | 1098 | ||
1111 | if (flags & LINUX_XFLAG_IMMUTABLE) | 1099 | if (flags & FS_IMMUTABLE_FL) |
1112 | xflags |= XFS_XFLAG_IMMUTABLE; | 1100 | xflags |= XFS_XFLAG_IMMUTABLE; |
1113 | else | 1101 | else |
1114 | xflags &= ~XFS_XFLAG_IMMUTABLE; | 1102 | xflags &= ~XFS_XFLAG_IMMUTABLE; |
1115 | if (flags & LINUX_XFLAG_APPEND) | 1103 | if (flags & FS_APPEND_FL) |
1116 | xflags |= XFS_XFLAG_APPEND; | 1104 | xflags |= XFS_XFLAG_APPEND; |
1117 | else | 1105 | else |
1118 | xflags &= ~XFS_XFLAG_APPEND; | 1106 | xflags &= ~XFS_XFLAG_APPEND; |
1119 | if (flags & LINUX_XFLAG_SYNC) | 1107 | if (flags & FS_SYNC_FL) |
1120 | xflags |= XFS_XFLAG_SYNC; | 1108 | xflags |= XFS_XFLAG_SYNC; |
1121 | else | 1109 | else |
1122 | xflags &= ~XFS_XFLAG_SYNC; | 1110 | xflags &= ~XFS_XFLAG_SYNC; |
1123 | if (flags & LINUX_XFLAG_NOATIME) | 1111 | if (flags & FS_NOATIME_FL) |
1124 | xflags |= XFS_XFLAG_NOATIME; | 1112 | xflags |= XFS_XFLAG_NOATIME; |
1125 | else | 1113 | else |
1126 | xflags &= ~XFS_XFLAG_NOATIME; | 1114 | xflags &= ~XFS_XFLAG_NOATIME; |
1127 | if (flags & LINUX_XFLAG_NODUMP) | 1115 | if (flags & FS_NODUMP_FL) |
1128 | xflags |= XFS_XFLAG_NODUMP; | 1116 | xflags |= XFS_XFLAG_NODUMP; |
1129 | else | 1117 | else |
1130 | xflags &= ~XFS_XFLAG_NODUMP; | 1118 | xflags &= ~XFS_XFLAG_NODUMP; |
@@ -1139,15 +1127,15 @@ xfs_di2lxflags( | |||
1139 | unsigned int flags = 0; | 1127 | unsigned int flags = 0; |
1140 | 1128 | ||
1141 | if (di_flags & XFS_DIFLAG_IMMUTABLE) | 1129 | if (di_flags & XFS_DIFLAG_IMMUTABLE) |
1142 | flags |= LINUX_XFLAG_IMMUTABLE; | 1130 | flags |= FS_IMMUTABLE_FL; |
1143 | if (di_flags & XFS_DIFLAG_APPEND) | 1131 | if (di_flags & XFS_DIFLAG_APPEND) |
1144 | flags |= LINUX_XFLAG_APPEND; | 1132 | flags |= FS_APPEND_FL; |
1145 | if (di_flags & XFS_DIFLAG_SYNC) | 1133 | if (di_flags & XFS_DIFLAG_SYNC) |
1146 | flags |= LINUX_XFLAG_SYNC; | 1134 | flags |= FS_SYNC_FL; |
1147 | if (di_flags & XFS_DIFLAG_NOATIME) | 1135 | if (di_flags & XFS_DIFLAG_NOATIME) |
1148 | flags |= LINUX_XFLAG_NOATIME; | 1136 | flags |= FS_NOATIME_FL; |
1149 | if (di_flags & XFS_DIFLAG_NODUMP) | 1137 | if (di_flags & XFS_DIFLAG_NODUMP) |
1150 | flags |= LINUX_XFLAG_NODUMP; | 1138 | flags |= FS_NODUMP_FL; |
1151 | return flags; | 1139 | return flags; |
1152 | } | 1140 | } |
1153 | 1141 | ||
@@ -1247,9 +1235,9 @@ xfs_ioc_xattr( | |||
1247 | break; | 1235 | break; |
1248 | } | 1236 | } |
1249 | 1237 | ||
1250 | if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \ | 1238 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ |
1251 | LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \ | 1239 | FS_NOATIME_FL | FS_NODUMP_FL | \ |
1252 | LINUX_XFLAG_SYNC)) { | 1240 | FS_SYNC_FL)) { |
1253 | error = -EOPNOTSUPP; | 1241 | error = -EOPNOTSUPP; |
1254 | break; | 1242 | break; |
1255 | } | 1243 | } |
@@ -1281,7 +1269,6 @@ xfs_ioc_xattr( | |||
1281 | STATIC int | 1269 | STATIC int |
1282 | xfs_ioc_getbmap( | 1270 | xfs_ioc_getbmap( |
1283 | bhv_desc_t *bdp, | 1271 | bhv_desc_t *bdp, |
1284 | struct file *filp, | ||
1285 | int ioflags, | 1272 | int ioflags, |
1286 | unsigned int cmd, | 1273 | unsigned int cmd, |
1287 | void __user *arg) | 1274 | void __user *arg) |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 3ba814ae3bba..0b5fa124bef2 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "xfs_itable.h" | 43 | #include "xfs_itable.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | 45 | #include "xfs_acl.h" |
46 | #include "xfs_cap.h" | ||
47 | #include "xfs_mac.h" | ||
48 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
49 | #include "xfs_buf_item.h" | 47 | #include "xfs_buf_item.h" |
50 | #include "xfs_utils.h" | 48 | #include "xfs_utils.h" |
@@ -250,13 +248,13 @@ xfs_init_security( | |||
250 | * | 248 | * |
251 | * XXX(hch): nfsd is broken, better fix it instead. | 249 | * XXX(hch): nfsd is broken, better fix it instead. |
252 | */ | 250 | */ |
253 | STATIC inline int | 251 | STATIC_INLINE int |
254 | xfs_has_fs_struct(struct task_struct *task) | 252 | xfs_has_fs_struct(struct task_struct *task) |
255 | { | 253 | { |
256 | return (task->fs != init_task.fs); | 254 | return (task->fs != init_task.fs); |
257 | } | 255 | } |
258 | 256 | ||
259 | STATIC inline void | 257 | STATIC void |
260 | xfs_cleanup_inode( | 258 | xfs_cleanup_inode( |
261 | bhv_vnode_t *dvp, | 259 | bhv_vnode_t *dvp, |
262 | bhv_vnode_t *vp, | 260 | bhv_vnode_t *vp, |
@@ -815,7 +813,7 @@ xfs_vn_removexattr( | |||
815 | } | 813 | } |
816 | 814 | ||
817 | 815 | ||
818 | struct inode_operations xfs_inode_operations = { | 816 | const struct inode_operations xfs_inode_operations = { |
819 | .permission = xfs_vn_permission, | 817 | .permission = xfs_vn_permission, |
820 | .truncate = xfs_vn_truncate, | 818 | .truncate = xfs_vn_truncate, |
821 | .getattr = xfs_vn_getattr, | 819 | .getattr = xfs_vn_getattr, |
@@ -826,7 +824,7 @@ struct inode_operations xfs_inode_operations = { | |||
826 | .removexattr = xfs_vn_removexattr, | 824 | .removexattr = xfs_vn_removexattr, |
827 | }; | 825 | }; |
828 | 826 | ||
829 | struct inode_operations xfs_dir_inode_operations = { | 827 | const struct inode_operations xfs_dir_inode_operations = { |
830 | .create = xfs_vn_create, | 828 | .create = xfs_vn_create, |
831 | .lookup = xfs_vn_lookup, | 829 | .lookup = xfs_vn_lookup, |
832 | .link = xfs_vn_link, | 830 | .link = xfs_vn_link, |
@@ -845,7 +843,7 @@ struct inode_operations xfs_dir_inode_operations = { | |||
845 | .removexattr = xfs_vn_removexattr, | 843 | .removexattr = xfs_vn_removexattr, |
846 | }; | 844 | }; |
847 | 845 | ||
848 | struct inode_operations xfs_symlink_inode_operations = { | 846 | const struct inode_operations xfs_symlink_inode_operations = { |
849 | .readlink = generic_readlink, | 847 | .readlink = generic_readlink, |
850 | .follow_link = xfs_vn_follow_link, | 848 | .follow_link = xfs_vn_follow_link, |
851 | .put_link = xfs_vn_put_link, | 849 | .put_link = xfs_vn_put_link, |
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index ad6173da5678..95a69398fce0 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h | |||
@@ -18,9 +18,9 @@ | |||
18 | #ifndef __XFS_IOPS_H__ | 18 | #ifndef __XFS_IOPS_H__ |
19 | #define __XFS_IOPS_H__ | 19 | #define __XFS_IOPS_H__ |
20 | 20 | ||
21 | extern struct inode_operations xfs_inode_operations; | 21 | extern const struct inode_operations xfs_inode_operations; |
22 | extern struct inode_operations xfs_dir_inode_operations; | 22 | extern const struct inode_operations xfs_dir_inode_operations; |
23 | extern struct inode_operations xfs_symlink_inode_operations; | 23 | extern const struct inode_operations xfs_symlink_inode_operations; |
24 | 24 | ||
25 | extern const struct file_operations xfs_file_operations; | 25 | extern const struct file_operations xfs_file_operations; |
26 | extern const struct file_operations xfs_dir_file_operations; | 26 | extern const struct file_operations xfs_dir_file_operations; |
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 2b0e0018738a..715adad7dd4d 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -109,16 +109,6 @@ | |||
109 | #undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ | 109 | #undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ |
110 | #endif | 110 | #endif |
111 | 111 | ||
112 | /* | ||
113 | * State flag for unwritten extent buffers. | ||
114 | * | ||
115 | * We need to be able to distinguish between these and delayed | ||
116 | * allocate buffers within XFS. The generic IO path code does | ||
117 | * not need to distinguish - we use the BH_Delay flag for both | ||
118 | * delalloc and these ondisk-uninitialised buffers. | ||
119 | */ | ||
120 | BUFFER_FNS(PrivateStart, unwritten); | ||
121 | |||
122 | #define restricted_chown xfs_params.restrict_chown.val | 112 | #define restricted_chown xfs_params.restrict_chown.val |
123 | #define irix_sgid_inherit xfs_params.sgid_inherit.val | 113 | #define irix_sgid_inherit xfs_params.sgid_inherit.val |
124 | #define irix_symlink_mode xfs_params.symlink_mode.val | 114 | #define irix_symlink_mode xfs_params.symlink_mode.val |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 65e79b471d49..ff8d64eba9f8 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "xfs_itable.h" | 43 | #include "xfs_itable.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | 45 | #include "xfs_acl.h" |
46 | #include "xfs_cap.h" | ||
47 | #include "xfs_mac.h" | ||
48 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
49 | #include "xfs_inode_item.h" | 47 | #include "xfs_inode_item.h" |
50 | #include "xfs_buf_item.h" | 48 | #include "xfs_buf_item.h" |
@@ -134,13 +132,11 @@ STATIC int | |||
134 | xfs_iozero( | 132 | xfs_iozero( |
135 | struct inode *ip, /* inode */ | 133 | struct inode *ip, /* inode */ |
136 | loff_t pos, /* offset in file */ | 134 | loff_t pos, /* offset in file */ |
137 | size_t count, /* size of data to zero */ | 135 | size_t count) /* size of data to zero */ |
138 | loff_t end_size) /* max file size to set */ | ||
139 | { | 136 | { |
140 | unsigned bytes; | 137 | unsigned bytes; |
141 | struct page *page; | 138 | struct page *page; |
142 | struct address_space *mapping; | 139 | struct address_space *mapping; |
143 | char *kaddr; | ||
144 | int status; | 140 | int status; |
145 | 141 | ||
146 | mapping = ip->i_mapping; | 142 | mapping = ip->i_mapping; |
@@ -158,26 +154,21 @@ xfs_iozero( | |||
158 | if (!page) | 154 | if (!page) |
159 | break; | 155 | break; |
160 | 156 | ||
161 | kaddr = kmap(page); | ||
162 | status = mapping->a_ops->prepare_write(NULL, page, offset, | 157 | status = mapping->a_ops->prepare_write(NULL, page, offset, |
163 | offset + bytes); | 158 | offset + bytes); |
164 | if (status) { | 159 | if (status) |
165 | goto unlock; | 160 | goto unlock; |
166 | } | ||
167 | 161 | ||
168 | memset((void *) (kaddr + offset), 0, bytes); | 162 | memclear_highpage_flush(page, offset, bytes); |
169 | flush_dcache_page(page); | 163 | |
170 | status = mapping->a_ops->commit_write(NULL, page, offset, | 164 | status = mapping->a_ops->commit_write(NULL, page, offset, |
171 | offset + bytes); | 165 | offset + bytes); |
172 | if (!status) { | 166 | if (!status) { |
173 | pos += bytes; | 167 | pos += bytes; |
174 | count -= bytes; | 168 | count -= bytes; |
175 | if (pos > i_size_read(ip)) | ||
176 | i_size_write(ip, pos < end_size ? pos : end_size); | ||
177 | } | 169 | } |
178 | 170 | ||
179 | unlock: | 171 | unlock: |
180 | kunmap(page); | ||
181 | unlock_page(page); | 172 | unlock_page(page); |
182 | page_cache_release(page); | 173 | page_cache_release(page); |
183 | if (status) | 174 | if (status) |
@@ -449,8 +440,8 @@ STATIC int /* error (positive) */ | |||
449 | xfs_zero_last_block( | 440 | xfs_zero_last_block( |
450 | struct inode *ip, | 441 | struct inode *ip, |
451 | xfs_iocore_t *io, | 442 | xfs_iocore_t *io, |
452 | xfs_fsize_t isize, | 443 | xfs_fsize_t offset, |
453 | xfs_fsize_t end_size) | 444 | xfs_fsize_t isize) |
454 | { | 445 | { |
455 | xfs_fileoff_t last_fsb; | 446 | xfs_fileoff_t last_fsb; |
456 | xfs_mount_t *mp = io->io_mount; | 447 | xfs_mount_t *mp = io->io_mount; |
@@ -459,7 +450,6 @@ xfs_zero_last_block( | |||
459 | int zero_len; | 450 | int zero_len; |
460 | int error = 0; | 451 | int error = 0; |
461 | xfs_bmbt_irec_t imap; | 452 | xfs_bmbt_irec_t imap; |
462 | loff_t loff; | ||
463 | 453 | ||
464 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); | 454 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); |
465 | 455 | ||
@@ -494,9 +484,10 @@ xfs_zero_last_block( | |||
494 | */ | 484 | */ |
495 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); | 485 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); |
496 | 486 | ||
497 | loff = XFS_FSB_TO_B(mp, last_fsb); | ||
498 | zero_len = mp->m_sb.sb_blocksize - zero_offset; | 487 | zero_len = mp->m_sb.sb_blocksize - zero_offset; |
499 | error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size); | 488 | if (isize + zero_len > offset) |
489 | zero_len = offset - isize; | ||
490 | error = xfs_iozero(ip, isize, zero_len); | ||
500 | 491 | ||
501 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); | 492 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); |
502 | ASSERT(error >= 0); | 493 | ASSERT(error >= 0); |
@@ -519,14 +510,15 @@ xfs_zero_eof( | |||
519 | bhv_vnode_t *vp, | 510 | bhv_vnode_t *vp, |
520 | xfs_iocore_t *io, | 511 | xfs_iocore_t *io, |
521 | xfs_off_t offset, /* starting I/O offset */ | 512 | xfs_off_t offset, /* starting I/O offset */ |
522 | xfs_fsize_t isize, /* current inode size */ | 513 | xfs_fsize_t isize) /* current inode size */ |
523 | xfs_fsize_t end_size) /* terminal inode size */ | ||
524 | { | 514 | { |
525 | struct inode *ip = vn_to_inode(vp); | 515 | struct inode *ip = vn_to_inode(vp); |
526 | xfs_fileoff_t start_zero_fsb; | 516 | xfs_fileoff_t start_zero_fsb; |
527 | xfs_fileoff_t end_zero_fsb; | 517 | xfs_fileoff_t end_zero_fsb; |
528 | xfs_fileoff_t zero_count_fsb; | 518 | xfs_fileoff_t zero_count_fsb; |
529 | xfs_fileoff_t last_fsb; | 519 | xfs_fileoff_t last_fsb; |
520 | xfs_fileoff_t zero_off; | ||
521 | xfs_fsize_t zero_len; | ||
530 | xfs_mount_t *mp = io->io_mount; | 522 | xfs_mount_t *mp = io->io_mount; |
531 | int nimaps; | 523 | int nimaps; |
532 | int error = 0; | 524 | int error = 0; |
@@ -540,7 +532,7 @@ xfs_zero_eof( | |||
540 | * First handle zeroing the block on which isize resides. | 532 | * First handle zeroing the block on which isize resides. |
541 | * We only zero a part of that block so it is handled specially. | 533 | * We only zero a part of that block so it is handled specially. |
542 | */ | 534 | */ |
543 | error = xfs_zero_last_block(ip, io, isize, end_size); | 535 | error = xfs_zero_last_block(ip, io, offset, isize); |
544 | if (error) { | 536 | if (error) { |
545 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); | 537 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); |
546 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); | 538 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); |
@@ -601,10 +593,13 @@ xfs_zero_eof( | |||
601 | */ | 593 | */ |
602 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); | 594 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); |
603 | 595 | ||
604 | error = xfs_iozero(ip, | 596 | zero_off = XFS_FSB_TO_B(mp, start_zero_fsb); |
605 | XFS_FSB_TO_B(mp, start_zero_fsb), | 597 | zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount); |
606 | XFS_FSB_TO_B(mp, imap.br_blockcount), | 598 | |
607 | end_size); | 599 | if ((zero_off + zero_len) > offset) |
600 | zero_len = offset - zero_off; | ||
601 | |||
602 | error = xfs_iozero(ip, zero_off, zero_len); | ||
608 | if (error) { | 603 | if (error) { |
609 | goto out_lock; | 604 | goto out_lock; |
610 | } | 605 | } |
@@ -783,8 +778,7 @@ start: | |||
783 | */ | 778 | */ |
784 | 779 | ||
785 | if (pos > isize) { | 780 | if (pos > isize) { |
786 | error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, | 781 | error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize); |
787 | isize, pos + count); | ||
788 | if (error) { | 782 | if (error) { |
789 | xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); | 783 | xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); |
790 | goto out_unlock_mutex; | 784 | goto out_unlock_mutex; |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index c77e62efb742..7ac51b1d2161 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h | |||
@@ -83,7 +83,7 @@ extern int xfs_bdstrat_cb(struct xfs_buf *); | |||
83 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); | 83 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); |
84 | 84 | ||
85 | extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t, | 85 | extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t, |
86 | xfs_fsize_t, xfs_fsize_t); | 86 | xfs_fsize_t); |
87 | extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, | 87 | extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, |
88 | const struct iovec *, unsigned int, | 88 | const struct iovec *, unsigned int, |
89 | loff_t *, int, struct cred *); | 89 | loff_t *, int, struct cred *); |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index b93265b7c79c..2f2c40db562e 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "xfs_itable.h" | 43 | #include "xfs_itable.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | 45 | #include "xfs_acl.h" |
46 | #include "xfs_cap.h" | ||
47 | #include "xfs_mac.h" | ||
48 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
49 | #include "xfs_buf_item.h" | 47 | #include "xfs_buf_item.h" |
50 | #include "xfs_utils.h" | 48 | #include "xfs_utils.h" |
@@ -58,10 +56,10 @@ | |||
58 | #include <linux/kthread.h> | 56 | #include <linux/kthread.h> |
59 | #include <linux/freezer.h> | 57 | #include <linux/freezer.h> |
60 | 58 | ||
61 | STATIC struct quotactl_ops xfs_quotactl_operations; | 59 | static struct quotactl_ops xfs_quotactl_operations; |
62 | STATIC struct super_operations xfs_super_operations; | 60 | static struct super_operations xfs_super_operations; |
63 | STATIC kmem_zone_t *xfs_vnode_zone; | 61 | static kmem_zone_t *xfs_vnode_zone; |
64 | STATIC kmem_zone_t *xfs_ioend_zone; | 62 | static kmem_zone_t *xfs_ioend_zone; |
65 | mempool_t *xfs_ioend_pool; | 63 | mempool_t *xfs_ioend_pool; |
66 | 64 | ||
67 | STATIC struct xfs_mount_args * | 65 | STATIC struct xfs_mount_args * |
@@ -121,7 +119,7 @@ xfs_max_file_offset( | |||
121 | return (((__uint64_t)pagefactor) << bitshift) - 1; | 119 | return (((__uint64_t)pagefactor) << bitshift) - 1; |
122 | } | 120 | } |
123 | 121 | ||
124 | STATIC __inline__ void | 122 | STATIC_INLINE void |
125 | xfs_set_inodeops( | 123 | xfs_set_inodeops( |
126 | struct inode *inode) | 124 | struct inode *inode) |
127 | { | 125 | { |
@@ -147,7 +145,7 @@ xfs_set_inodeops( | |||
147 | } | 145 | } |
148 | } | 146 | } |
149 | 147 | ||
150 | STATIC __inline__ void | 148 | STATIC_INLINE void |
151 | xfs_revalidate_inode( | 149 | xfs_revalidate_inode( |
152 | xfs_mount_t *mp, | 150 | xfs_mount_t *mp, |
153 | bhv_vnode_t *vp, | 151 | bhv_vnode_t *vp, |
@@ -553,7 +551,6 @@ vfs_sync_worker( | |||
553 | error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \ | 551 | error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \ |
554 | SYNC_ATTR | SYNC_REFCACHE, NULL); | 552 | SYNC_ATTR | SYNC_REFCACHE, NULL); |
555 | vfsp->vfs_sync_seq++; | 553 | vfsp->vfs_sync_seq++; |
556 | wmb(); | ||
557 | wake_up(&vfsp->vfs_wait_single_sync_task); | 554 | wake_up(&vfsp->vfs_wait_single_sync_task); |
558 | } | 555 | } |
559 | 556 | ||
@@ -659,9 +656,17 @@ xfs_fs_sync_super( | |||
659 | int error; | 656 | int error; |
660 | int flags; | 657 | int flags; |
661 | 658 | ||
662 | if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) | 659 | if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) { |
663 | flags = SYNC_QUIESCE; | 660 | /* |
664 | else | 661 | * First stage of freeze - no more writers will make progress |
662 | * now we are here, so we flush delwri and delalloc buffers | ||
663 | * here, then wait for all I/O to complete. Data is frozen at | ||
664 | * that point. Metadata is not frozen, transactions can still | ||
665 | * occur here so don't bother flushing the buftarg (i.e | ||
666 | * SYNC_QUIESCE) because it'll just get dirty again. | ||
667 | */ | ||
668 | flags = SYNC_FSDATA | SYNC_DELWRI | SYNC_WAIT | SYNC_IOWAIT; | ||
669 | } else | ||
665 | flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0); | 670 | flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0); |
666 | 671 | ||
667 | error = bhv_vfs_sync(vfsp, flags, NULL); | 672 | error = bhv_vfs_sync(vfsp, flags, NULL); |
@@ -873,7 +878,7 @@ xfs_fs_get_sb( | |||
873 | mnt); | 878 | mnt); |
874 | } | 879 | } |
875 | 880 | ||
876 | STATIC struct super_operations xfs_super_operations = { | 881 | static struct super_operations xfs_super_operations = { |
877 | .alloc_inode = xfs_fs_alloc_inode, | 882 | .alloc_inode = xfs_fs_alloc_inode, |
878 | .destroy_inode = xfs_fs_destroy_inode, | 883 | .destroy_inode = xfs_fs_destroy_inode, |
879 | .write_inode = xfs_fs_write_inode, | 884 | .write_inode = xfs_fs_write_inode, |
@@ -887,7 +892,7 @@ STATIC struct super_operations xfs_super_operations = { | |||
887 | .show_options = xfs_fs_show_options, | 892 | .show_options = xfs_fs_show_options, |
888 | }; | 893 | }; |
889 | 894 | ||
890 | STATIC struct quotactl_ops xfs_quotactl_operations = { | 895 | static struct quotactl_ops xfs_quotactl_operations = { |
891 | .quota_sync = xfs_fs_quotasync, | 896 | .quota_sync = xfs_fs_quotasync, |
892 | .get_xstate = xfs_fs_getxstate, | 897 | .get_xstate = xfs_fs_getxstate, |
893 | .set_xstate = xfs_fs_setxstate, | 898 | .set_xstate = xfs_fs_setxstate, |
@@ -895,7 +900,7 @@ STATIC struct quotactl_ops xfs_quotactl_operations = { | |||
895 | .set_xquota = xfs_fs_setxquota, | 900 | .set_xquota = xfs_fs_setxquota, |
896 | }; | 901 | }; |
897 | 902 | ||
898 | STATIC struct file_system_type xfs_fs_type = { | 903 | static struct file_system_type xfs_fs_type = { |
899 | .owner = THIS_MODULE, | 904 | .owner = THIS_MODULE, |
900 | .name = "xfs", | 905 | .name = "xfs", |
901 | .get_sb = xfs_fs_get_sb, | 906 | .get_sb = xfs_fs_get_sb, |
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index af246532fbfb..cd6eaa44aa2b 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c | |||
@@ -54,102 +54,204 @@ xfs_stats_clear_proc_handler( | |||
54 | } | 54 | } |
55 | #endif /* CONFIG_PROC_FS */ | 55 | #endif /* CONFIG_PROC_FS */ |
56 | 56 | ||
57 | STATIC ctl_table xfs_table[] = { | 57 | static ctl_table xfs_table[] = { |
58 | {XFS_RESTRICT_CHOWN, "restrict_chown", &xfs_params.restrict_chown.val, | 58 | { |
59 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | 59 | .ctl_name = XFS_RESTRICT_CHOWN, |
60 | &sysctl_intvec, NULL, | 60 | .procname = "restrict_chown", |
61 | &xfs_params.restrict_chown.min, &xfs_params.restrict_chown.max}, | 61 | .data = &xfs_params.restrict_chown.val, |
62 | 62 | .maxlen = sizeof(int), | |
63 | {XFS_SGID_INHERIT, "irix_sgid_inherit", &xfs_params.sgid_inherit.val, | 63 | .mode = 0644, |
64 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | 64 | .proc_handler = &proc_dointvec_minmax, |
65 | &sysctl_intvec, NULL, | 65 | .strategy = &sysctl_intvec, |
66 | &xfs_params.sgid_inherit.min, &xfs_params.sgid_inherit.max}, | 66 | .extra1 = &xfs_params.restrict_chown.min, |
67 | 67 | .extra2 = &xfs_params.restrict_chown.max | |
68 | {XFS_SYMLINK_MODE, "irix_symlink_mode", &xfs_params.symlink_mode.val, | 68 | }, |
69 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | 69 | { |
70 | &sysctl_intvec, NULL, | 70 | .ctl_name = XFS_SGID_INHERIT, |
71 | &xfs_params.symlink_mode.min, &xfs_params.symlink_mode.max}, | 71 | .procname = "irix_sgid_inherit", |
72 | 72 | .data = &xfs_params.sgid_inherit.val, | |
73 | {XFS_PANIC_MASK, "panic_mask", &xfs_params.panic_mask.val, | 73 | .maxlen = sizeof(int), |
74 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | 74 | .mode = 0644, |
75 | &sysctl_intvec, NULL, | 75 | .proc_handler = &proc_dointvec_minmax, |
76 | &xfs_params.panic_mask.min, &xfs_params.panic_mask.max}, | 76 | .strategy = &sysctl_intvec, |
77 | 77 | .extra1 = &xfs_params.sgid_inherit.min, | |
78 | {XFS_ERRLEVEL, "error_level", &xfs_params.error_level.val, | 78 | .extra2 = &xfs_params.sgid_inherit.max |
79 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | 79 | }, |
80 | &sysctl_intvec, NULL, | 80 | { |
81 | &xfs_params.error_level.min, &xfs_params.error_level.max}, | 81 | .ctl_name = XFS_SYMLINK_MODE, |
82 | 82 | .procname = "irix_symlink_mode", | |
83 | {XFS_SYNCD_TIMER, "xfssyncd_centisecs", &xfs_params.syncd_timer.val, | 83 | .data = &xfs_params.symlink_mode.val, |
84 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | 84 | .maxlen = sizeof(int), |
85 | &sysctl_intvec, NULL, | 85 | .mode = 0644, |
86 | &xfs_params.syncd_timer.min, &xfs_params.syncd_timer.max}, | 86 | .proc_handler = &proc_dointvec_minmax, |
87 | 87 | .strategy = &sysctl_intvec, | |
88 | {XFS_INHERIT_SYNC, "inherit_sync", &xfs_params.inherit_sync.val, | 88 | .extra1 = &xfs_params.symlink_mode.min, |
89 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | 89 | .extra2 = &xfs_params.symlink_mode.max |
90 | &sysctl_intvec, NULL, | 90 | }, |
91 | &xfs_params.inherit_sync.min, &xfs_params.inherit_sync.max}, | 91 | { |
92 | 92 | .ctl_name = XFS_PANIC_MASK, | |
93 | {XFS_INHERIT_NODUMP, "inherit_nodump", &xfs_params.inherit_nodump.val, | 93 | .procname = "panic_mask", |
94 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | 94 | .data = &xfs_params.panic_mask.val, |
95 | &sysctl_intvec, NULL, | 95 | .maxlen = sizeof(int), |
96 | &xfs_params.inherit_nodump.min, &xfs_params.inherit_nodump.max}, | 96 | .mode = 0644, |
97 | 97 | .proc_handler = &proc_dointvec_minmax, | |
98 | {XFS_INHERIT_NOATIME, "inherit_noatime", &xfs_params.inherit_noatim.val, | 98 | .strategy = &sysctl_intvec, |
99 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | 99 | .extra1 = &xfs_params.panic_mask.min, |
100 | &sysctl_intvec, NULL, | 100 | .extra2 = &xfs_params.panic_mask.max |
101 | &xfs_params.inherit_noatim.min, &xfs_params.inherit_noatim.max}, | 101 | }, |
102 | |||
103 | {XFS_BUF_TIMER, "xfsbufd_centisecs", &xfs_params.xfs_buf_timer.val, | ||
104 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | ||
105 | &sysctl_intvec, NULL, | ||
106 | &xfs_params.xfs_buf_timer.min, &xfs_params.xfs_buf_timer.max}, | ||
107 | |||
108 | {XFS_BUF_AGE, "age_buffer_centisecs", &xfs_params.xfs_buf_age.val, | ||
109 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | ||
110 | &sysctl_intvec, NULL, | ||
111 | &xfs_params.xfs_buf_age.min, &xfs_params.xfs_buf_age.max}, | ||
112 | |||
113 | {XFS_INHERIT_NOSYM, "inherit_nosymlinks", &xfs_params.inherit_nosym.val, | ||
114 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | ||
115 | &sysctl_intvec, NULL, | ||
116 | &xfs_params.inherit_nosym.min, &xfs_params.inherit_nosym.max}, | ||
117 | |||
118 | {XFS_ROTORSTEP, "rotorstep", &xfs_params.rotorstep.val, | ||
119 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | ||
120 | &sysctl_intvec, NULL, | ||
121 | &xfs_params.rotorstep.min, &xfs_params.rotorstep.max}, | ||
122 | |||
123 | {XFS_INHERIT_NODFRG, "inherit_nodefrag", &xfs_params.inherit_nodfrg.val, | ||
124 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | ||
125 | &sysctl_intvec, NULL, | ||
126 | &xfs_params.inherit_nodfrg.min, &xfs_params.inherit_nodfrg.max}, | ||
127 | 102 | ||
103 | { | ||
104 | .ctl_name = XFS_ERRLEVEL, | ||
105 | .procname = "error_level", | ||
106 | .data = &xfs_params.error_level.val, | ||
107 | .maxlen = sizeof(int), | ||
108 | .mode = 0644, | ||
109 | .proc_handler = &proc_dointvec_minmax, | ||
110 | .strategy = &sysctl_intvec, | ||
111 | .extra1 = &xfs_params.error_level.min, | ||
112 | .extra2 = &xfs_params.error_level.max | ||
113 | }, | ||
114 | { | ||
115 | .ctl_name = XFS_SYNCD_TIMER, | ||
116 | .procname = "xfssyncd_centisecs", | ||
117 | .data = &xfs_params.syncd_timer.val, | ||
118 | .maxlen = sizeof(int), | ||
119 | .mode = 0644, | ||
120 | .proc_handler = &proc_dointvec_minmax, | ||
121 | .strategy = &sysctl_intvec, | ||
122 | .extra1 = &xfs_params.syncd_timer.min, | ||
123 | .extra2 = &xfs_params.syncd_timer.max | ||
124 | }, | ||
125 | { | ||
126 | .ctl_name = XFS_INHERIT_SYNC, | ||
127 | .procname = "inherit_sync", | ||
128 | .data = &xfs_params.inherit_sync.val, | ||
129 | .maxlen = sizeof(int), | ||
130 | .mode = 0644, | ||
131 | .proc_handler = &proc_dointvec_minmax, | ||
132 | .strategy = &sysctl_intvec, | ||
133 | .extra1 = &xfs_params.inherit_sync.min, | ||
134 | .extra2 = &xfs_params.inherit_sync.max | ||
135 | }, | ||
136 | { | ||
137 | .ctl_name = XFS_INHERIT_NODUMP, | ||
138 | .procname = "inherit_nodump", | ||
139 | .data = &xfs_params.inherit_nodump.val, | ||
140 | .maxlen = sizeof(int), | ||
141 | .mode = 0644, | ||
142 | .proc_handler = &proc_dointvec_minmax, | ||
143 | .strategy = &sysctl_intvec, | ||
144 | .extra1 = &xfs_params.inherit_nodump.min, | ||
145 | .extra2 = &xfs_params.inherit_nodump.max | ||
146 | }, | ||
147 | { | ||
148 | .ctl_name = XFS_INHERIT_NOATIME, | ||
149 | .procname = "inherit_noatime", | ||
150 | .data = &xfs_params.inherit_noatim.val, | ||
151 | .maxlen = sizeof(int), | ||
152 | .mode = 0644, | ||
153 | .proc_handler = &proc_dointvec_minmax, | ||
154 | .strategy = &sysctl_intvec, | ||
155 | .extra1 = &xfs_params.inherit_noatim.min, | ||
156 | .extra2 = &xfs_params.inherit_noatim.max | ||
157 | }, | ||
158 | { | ||
159 | .ctl_name = XFS_BUF_TIMER, | ||
160 | .procname = "xfsbufd_centisecs", | ||
161 | .data = &xfs_params.xfs_buf_timer.val, | ||
162 | .maxlen = sizeof(int), | ||
163 | .mode = 0644, | ||
164 | .proc_handler = &proc_dointvec_minmax, | ||
165 | .strategy = &sysctl_intvec, | ||
166 | .extra1 = &xfs_params.xfs_buf_timer.min, | ||
167 | .extra2 = &xfs_params.xfs_buf_timer.max | ||
168 | }, | ||
169 | { | ||
170 | .ctl_name = XFS_BUF_AGE, | ||
171 | .procname = "age_buffer_centisecs", | ||
172 | .data = &xfs_params.xfs_buf_age.val, | ||
173 | .maxlen = sizeof(int), | ||
174 | .mode = 0644, | ||
175 | .proc_handler = &proc_dointvec_minmax, | ||
176 | .strategy = &sysctl_intvec, | ||
177 | .extra1 = &xfs_params.xfs_buf_age.min, | ||
178 | .extra2 = &xfs_params.xfs_buf_age.max | ||
179 | }, | ||
180 | { | ||
181 | .ctl_name = XFS_INHERIT_NOSYM, | ||
182 | .procname = "inherit_nosymlinks", | ||
183 | .data = &xfs_params.inherit_nosym.val, | ||
184 | .maxlen = sizeof(int), | ||
185 | .mode = 0644, | ||
186 | .proc_handler = &proc_dointvec_minmax, | ||
187 | .strategy = &sysctl_intvec, | ||
188 | .extra1 = &xfs_params.inherit_nosym.min, | ||
189 | .extra2 = &xfs_params.inherit_nosym.max | ||
190 | }, | ||
191 | { | ||
192 | .ctl_name = XFS_ROTORSTEP, | ||
193 | .procname = "rotorstep", | ||
194 | .data = &xfs_params.rotorstep.val, | ||
195 | .maxlen = sizeof(int), | ||
196 | .mode = 0644, | ||
197 | .proc_handler = &proc_dointvec_minmax, | ||
198 | .strategy = &sysctl_intvec, | ||
199 | .extra1 = &xfs_params.rotorstep.min, | ||
200 | .extra2 = &xfs_params.rotorstep.max | ||
201 | }, | ||
202 | { | ||
203 | .ctl_name = XFS_INHERIT_NODFRG, | ||
204 | .procname = "inherit_nodefrag", | ||
205 | .data = &xfs_params.inherit_nodfrg.val, | ||
206 | .maxlen = sizeof(int), | ||
207 | .mode = 0644, | ||
208 | .proc_handler = &proc_dointvec_minmax, | ||
209 | .strategy = &sysctl_intvec, | ||
210 | .extra1 = &xfs_params.inherit_nodfrg.min, | ||
211 | .extra2 = &xfs_params.inherit_nodfrg.max | ||
212 | }, | ||
128 | /* please keep this the last entry */ | 213 | /* please keep this the last entry */ |
129 | #ifdef CONFIG_PROC_FS | 214 | #ifdef CONFIG_PROC_FS |
130 | {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val, | 215 | { |
131 | sizeof(int), 0644, NULL, &xfs_stats_clear_proc_handler, | 216 | .ctl_name = XFS_STATS_CLEAR, |
132 | &sysctl_intvec, NULL, | 217 | .procname = "stats_clear", |
133 | &xfs_params.stats_clear.min, &xfs_params.stats_clear.max}, | 218 | .data = &xfs_params.stats_clear.val, |
219 | .maxlen = sizeof(int), | ||
220 | .mode = 0644, | ||
221 | .proc_handler = &xfs_stats_clear_proc_handler, | ||
222 | .strategy = &sysctl_intvec, | ||
223 | .extra1 = &xfs_params.stats_clear.min, | ||
224 | .extra2 = &xfs_params.stats_clear.max | ||
225 | }, | ||
134 | #endif /* CONFIG_PROC_FS */ | 226 | #endif /* CONFIG_PROC_FS */ |
135 | 227 | ||
136 | {0} | 228 | {} |
137 | }; | 229 | }; |
138 | 230 | ||
139 | STATIC ctl_table xfs_dir_table[] = { | 231 | static ctl_table xfs_dir_table[] = { |
140 | {FS_XFS, "xfs", NULL, 0, 0555, xfs_table}, | 232 | { |
141 | {0} | 233 | .ctl_name = FS_XFS, |
234 | .procname = "xfs", | ||
235 | .mode = 0555, | ||
236 | .child = xfs_table | ||
237 | }, | ||
238 | {} | ||
142 | }; | 239 | }; |
143 | 240 | ||
144 | STATIC ctl_table xfs_root_table[] = { | 241 | static ctl_table xfs_root_table[] = { |
145 | {CTL_FS, "fs", NULL, 0, 0555, xfs_dir_table}, | 242 | { |
146 | {0} | 243 | .ctl_name = CTL_FS, |
244 | .procname = "fs", | ||
245 | .mode = 0555, | ||
246 | .child = xfs_dir_table | ||
247 | }, | ||
248 | {} | ||
147 | }; | 249 | }; |
148 | 250 | ||
149 | void | 251 | void |
150 | xfs_sysctl_register(void) | 252 | xfs_sysctl_register(void) |
151 | { | 253 | { |
152 | xfs_table_header = register_sysctl_table(xfs_root_table, 1); | 254 | xfs_table_header = register_sysctl_table(xfs_root_table); |
153 | } | 255 | } |
154 | 256 | ||
155 | void | 257 | void |
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index da255bdf5260..e2c2ce98ab5b 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h | |||
@@ -91,7 +91,7 @@ typedef enum { | |||
91 | #define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ | 91 | #define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ |
92 | #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ | 92 | #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ |
93 | #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ | 93 | #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ |
94 | #define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */ | 94 | #define SYNC_IOWAIT 0x0100 /* wait for all I/O to complete */ |
95 | 95 | ||
96 | #define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */ | 96 | #define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */ |
97 | #define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */ | 97 | #define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */ |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 553fa731ade5..ada24baf88de 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c | |||
@@ -26,7 +26,7 @@ DEFINE_SPINLOCK(vnumber_lock); | |||
26 | */ | 26 | */ |
27 | #define NVSYNC 37 | 27 | #define NVSYNC 37 |
28 | #define vptosync(v) (&vsync[((unsigned long)v) % NVSYNC]) | 28 | #define vptosync(v) (&vsync[((unsigned long)v) % NVSYNC]) |
29 | STATIC wait_queue_head_t vsync[NVSYNC]; | 29 | static wait_queue_head_t vsync[NVSYNC]; |
30 | 30 | ||
31 | void | 31 | void |
32 | vn_init(void) | 32 | vn_init(void) |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 515f5fdea57a..b76118cf4897 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
@@ -489,14 +489,14 @@ static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp) | |||
489 | #define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock) | 489 | #define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock) |
490 | #define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s) | 490 | #define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s) |
491 | 491 | ||
492 | static __inline__ void vn_flagset(struct bhv_vnode *vp, uint flag) | 492 | STATIC_INLINE void vn_flagset(struct bhv_vnode *vp, uint flag) |
493 | { | 493 | { |
494 | spin_lock(&vp->v_lock); | 494 | spin_lock(&vp->v_lock); |
495 | vp->v_flag |= flag; | 495 | vp->v_flag |= flag; |
496 | spin_unlock(&vp->v_lock); | 496 | spin_unlock(&vp->v_lock); |
497 | } | 497 | } |
498 | 498 | ||
499 | static __inline__ uint vn_flagclr(struct bhv_vnode *vp, uint flag) | 499 | STATIC_INLINE uint vn_flagclr(struct bhv_vnode *vp, uint flag) |
500 | { | 500 | { |
501 | uint cleared; | 501 | uint cleared; |
502 | 502 | ||
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 3aa771531856..4adaf13aac6f 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "xfs_itable.h" | 43 | #include "xfs_itable.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | 45 | #include "xfs_acl.h" |
46 | #include "xfs_cap.h" | ||
47 | #include "xfs_mac.h" | ||
48 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
49 | #include "xfs_buf_item.h" | 47 | #include "xfs_buf_item.h" |
50 | #include "xfs_trans_space.h" | 48 | #include "xfs_trans_space.h" |
@@ -484,7 +482,7 @@ xfs_qm_dqalloc( | |||
484 | 482 | ||
485 | xfs_trans_bhold(tp, bp); | 483 | xfs_trans_bhold(tp, bp); |
486 | 484 | ||
487 | if ((error = xfs_bmap_finish(tpp, &flist, firstblock, &committed))) { | 485 | if ((error = xfs_bmap_finish(tpp, &flist, &committed))) { |
488 | goto error1; | 486 | goto error1; |
489 | } | 487 | } |
490 | 488 | ||
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 33ad5af386e0..ddb61fe22a5c 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "xfs_itable.h" | 43 | #include "xfs_itable.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | 45 | #include "xfs_acl.h" |
46 | #include "xfs_cap.h" | ||
47 | #include "xfs_mac.h" | ||
48 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
49 | #include "xfs_buf_item.h" | 47 | #include "xfs_buf_item.h" |
50 | #include "xfs_trans_priv.h" | 48 | #include "xfs_trans_priv.h" |
@@ -399,7 +397,7 @@ xfs_qm_dquot_logitem_committing( | |||
399 | /* | 397 | /* |
400 | * This is the ops vector for dquots | 398 | * This is the ops vector for dquots |
401 | */ | 399 | */ |
402 | STATIC struct xfs_item_ops xfs_dquot_item_ops = { | 400 | static struct xfs_item_ops xfs_dquot_item_ops = { |
403 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size, | 401 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size, |
404 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 402 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) |
405 | xfs_qm_dquot_logitem_format, | 403 | xfs_qm_dquot_logitem_format, |
@@ -606,7 +604,7 @@ xfs_qm_qoffend_logitem_committing(xfs_qoff_logitem_t *qip, xfs_lsn_t commit_lsn) | |||
606 | return; | 604 | return; |
607 | } | 605 | } |
608 | 606 | ||
609 | STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { | 607 | static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { |
610 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size, | 608 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size, |
611 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 609 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) |
612 | xfs_qm_qoff_logitem_format, | 610 | xfs_qm_qoff_logitem_format, |
@@ -628,7 +626,7 @@ STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { | |||
628 | /* | 626 | /* |
629 | * This is the ops vector shared by all quotaoff-start log items. | 627 | * This is the ops vector shared by all quotaoff-start log items. |
630 | */ | 628 | */ |
631 | STATIC struct xfs_item_ops xfs_qm_qoff_logitem_ops = { | 629 | static struct xfs_item_ops xfs_qm_qoff_logitem_ops = { |
632 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size, | 630 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size, |
633 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 631 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) |
634 | xfs_qm_qoff_logitem_format, | 632 | xfs_qm_qoff_logitem_format, |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 7c6a3a50379e..1de2acdc7f70 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -44,8 +44,6 @@ | |||
44 | #include "xfs_bmap.h" | 44 | #include "xfs_bmap.h" |
45 | #include "xfs_rw.h" | 45 | #include "xfs_rw.h" |
46 | #include "xfs_acl.h" | 46 | #include "xfs_acl.h" |
47 | #include "xfs_cap.h" | ||
48 | #include "xfs_mac.h" | ||
49 | #include "xfs_attr.h" | 47 | #include "xfs_attr.h" |
50 | #include "xfs_buf_item.h" | 48 | #include "xfs_buf_item.h" |
51 | #include "xfs_trans_space.h" | 49 | #include "xfs_trans_space.h" |
@@ -64,10 +62,10 @@ uint ndquot; | |||
64 | 62 | ||
65 | kmem_zone_t *qm_dqzone; | 63 | kmem_zone_t *qm_dqzone; |
66 | kmem_zone_t *qm_dqtrxzone; | 64 | kmem_zone_t *qm_dqtrxzone; |
67 | STATIC kmem_shaker_t xfs_qm_shaker; | 65 | static kmem_shaker_t xfs_qm_shaker; |
68 | 66 | ||
69 | STATIC cred_t xfs_zerocr; | 67 | static cred_t xfs_zerocr; |
70 | STATIC xfs_inode_t xfs_zeroino; | 68 | static xfs_inode_t xfs_zeroino; |
71 | 69 | ||
72 | STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); | 70 | STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); |
73 | STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); | 71 | STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); |
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index db8872be8c87..d2cdb8a2aad6 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c | |||
@@ -44,8 +44,6 @@ | |||
44 | #include "xfs_error.h" | 44 | #include "xfs_error.h" |
45 | #include "xfs_rw.h" | 45 | #include "xfs_rw.h" |
46 | #include "xfs_acl.h" | 46 | #include "xfs_acl.h" |
47 | #include "xfs_cap.h" | ||
48 | #include "xfs_mac.h" | ||
49 | #include "xfs_attr.h" | 47 | #include "xfs_attr.h" |
50 | #include "xfs_buf_item.h" | 48 | #include "xfs_buf_item.h" |
51 | #include "xfs_qm.h" | 49 | #include "xfs_qm.h" |
@@ -384,7 +382,7 @@ xfs_qm_dqrele_null( | |||
384 | } | 382 | } |
385 | 383 | ||
386 | 384 | ||
387 | STATIC struct xfs_qmops xfs_qmcore_xfs = { | 385 | static struct xfs_qmops xfs_qmcore_xfs = { |
388 | .xfs_qminit = xfs_qm_newmount, | 386 | .xfs_qminit = xfs_qm_newmount, |
389 | .xfs_qmdone = xfs_qm_unmount_quotadestroy, | 387 | .xfs_qmdone = xfs_qm_unmount_quotadestroy, |
390 | .xfs_qmmount = xfs_qm_endmount, | 388 | .xfs_qmmount = xfs_qm_endmount, |
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c index 6f858fb81a36..709f5f545cf5 100644 --- a/fs/xfs/quota/xfs_qm_stats.c +++ b/fs/xfs/quota/xfs_qm_stats.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "xfs_error.h" | 43 | #include "xfs_error.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | 45 | #include "xfs_acl.h" |
46 | #include "xfs_cap.h" | ||
47 | #include "xfs_mac.h" | ||
48 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
49 | #include "xfs_buf_item.h" | 47 | #include "xfs_buf_item.h" |
50 | #include "xfs_qm.h" | 48 | #include "xfs_qm.h" |
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index ed620c4d1594..716f562aa8b2 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
@@ -46,8 +46,6 @@ | |||
46 | #include "xfs_error.h" | 46 | #include "xfs_error.h" |
47 | #include "xfs_rw.h" | 47 | #include "xfs_rw.h" |
48 | #include "xfs_acl.h" | 48 | #include "xfs_acl.h" |
49 | #include "xfs_cap.h" | ||
50 | #include "xfs_mac.h" | ||
51 | #include "xfs_attr.h" | 49 | #include "xfs_attr.h" |
52 | #include "xfs_buf_item.h" | 50 | #include "xfs_buf_item.h" |
53 | #include "xfs_utils.h" | 51 | #include "xfs_utils.h" |
@@ -134,7 +132,7 @@ xfs_qm_quotactl( | |||
134 | break; | 132 | break; |
135 | 133 | ||
136 | case Q_XQUOTASYNC: | 134 | case Q_XQUOTASYNC: |
137 | return (xfs_sync_inodes(mp, SYNC_DELWRI, 0, NULL)); | 135 | return (xfs_sync_inodes(mp, SYNC_DELWRI, NULL)); |
138 | 136 | ||
139 | default: | 137 | default: |
140 | break; | 138 | break; |
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 0242e9666e8e..d7491e7b1f3b 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "xfs_error.h" | 43 | #include "xfs_error.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | 45 | #include "xfs_acl.h" |
46 | #include "xfs_cap.h" | ||
47 | #include "xfs_mac.h" | ||
48 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
49 | #include "xfs_buf_item.h" | 47 | #include "xfs_buf_item.h" |
50 | #include "xfs_trans_priv.h" | 48 | #include "xfs_trans_priv.h" |
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index 4363512d2f90..08bbd3cb87ae 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include "debug.h" | 19 | #include "debug.h" |
20 | #include "spin.h" | 20 | #include "spin.h" |
21 | 21 | ||
22 | static char message[256]; /* keep it off the stack */ | 22 | static char message[1024]; /* keep it off the stack */ |
23 | static DEFINE_SPINLOCK(xfs_err_lock); | 23 | static DEFINE_SPINLOCK(xfs_err_lock); |
24 | 24 | ||
25 | /* Translate from CE_FOO to KERN_FOO, err_level(CE_FOO) == KERN_FOO */ | 25 | /* Translate from CE_FOO to KERN_FOO, err_level(CE_FOO) == KERN_FOO */ |
@@ -44,13 +44,14 @@ cmn_err(register int level, char *fmt, ...) | |||
44 | spin_lock_irqsave(&xfs_err_lock,flags); | 44 | spin_lock_irqsave(&xfs_err_lock,flags); |
45 | va_start(ap, fmt); | 45 | va_start(ap, fmt); |
46 | if (*fmt == '!') fp++; | 46 | if (*fmt == '!') fp++; |
47 | len = vsprintf(message, fp, ap); | 47 | len = vsnprintf(message, sizeof(message), fp, ap); |
48 | if (level != CE_DEBUG && message[len-1] != '\n') | 48 | if (len >= sizeof(message)) |
49 | strcat(message, "\n"); | 49 | len = sizeof(message) - 1; |
50 | printk("%s%s", err_level[level], message); | 50 | if (message[len-1] == '\n') |
51 | message[len-1] = 0; | ||
52 | printk("%s%s\n", err_level[level], message); | ||
51 | va_end(ap); | 53 | va_end(ap); |
52 | spin_unlock_irqrestore(&xfs_err_lock,flags); | 54 | spin_unlock_irqrestore(&xfs_err_lock,flags); |
53 | |||
54 | BUG_ON(level == CE_PANIC); | 55 | BUG_ON(level == CE_PANIC); |
55 | } | 56 | } |
56 | 57 | ||
@@ -64,11 +65,13 @@ icmn_err(register int level, char *fmt, va_list ap) | |||
64 | if(level > XFS_MAX_ERR_LEVEL) | 65 | if(level > XFS_MAX_ERR_LEVEL) |
65 | level = XFS_MAX_ERR_LEVEL; | 66 | level = XFS_MAX_ERR_LEVEL; |
66 | spin_lock_irqsave(&xfs_err_lock,flags); | 67 | spin_lock_irqsave(&xfs_err_lock,flags); |
67 | len = vsprintf(message, fmt, ap); | 68 | len = vsnprintf(message, sizeof(message), fmt, ap); |
68 | if (level != CE_DEBUG && message[len-1] != '\n') | 69 | if (len >= sizeof(message)) |
69 | strcat(message, "\n"); | 70 | len = sizeof(message) - 1; |
71 | if (message[len-1] == '\n') | ||
72 | message[len-1] = 0; | ||
73 | printk("%s%s\n", err_level[level], message); | ||
70 | spin_unlock_irqrestore(&xfs_err_lock,flags); | 74 | spin_unlock_irqrestore(&xfs_err_lock,flags); |
71 | printk("%s%s", err_level[level], message); | ||
72 | BUG_ON(level == CE_PANIC); | 75 | BUG_ON(level == CE_PANIC); |
73 | } | 76 | } |
74 | 77 | ||
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index 4f54dca662a8..2a70cc605ae3 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h | |||
@@ -38,13 +38,37 @@ extern void assfail(char *expr, char *f, int l); | |||
38 | 38 | ||
39 | #ifndef DEBUG | 39 | #ifndef DEBUG |
40 | # define ASSERT(expr) ((void)0) | 40 | # define ASSERT(expr) ((void)0) |
41 | #else | 41 | |
42 | #ifndef STATIC | ||
43 | # define STATIC static noinline | ||
44 | #endif | ||
45 | |||
46 | #ifndef STATIC_INLINE | ||
47 | # define STATIC_INLINE static inline | ||
48 | #endif | ||
49 | |||
50 | #else /* DEBUG */ | ||
51 | |||
42 | # define ASSERT(expr) ASSERT_ALWAYS(expr) | 52 | # define ASSERT(expr) ASSERT_ALWAYS(expr) |
43 | extern unsigned long random(void); | 53 | extern unsigned long random(void); |
44 | #endif | ||
45 | 54 | ||
46 | #ifndef STATIC | 55 | #ifndef STATIC |
47 | # define STATIC static | 56 | # define STATIC noinline |
48 | #endif | 57 | #endif |
49 | 58 | ||
59 | /* | ||
60 | * We stop inlining of inline functions in debug mode. | ||
61 | * Unfortunately, this means static inline in header files | ||
62 | * get multiple definitions, so they need to remain static. | ||
63 | * This then gives tonnes of warnings about unused but defined | ||
64 | * functions, so we need to add the unused attribute to prevent | ||
65 | * these spurious warnings. | ||
66 | */ | ||
67 | #ifndef STATIC_INLINE | ||
68 | # define STATIC_INLINE static __attribute__ ((unused)) noinline | ||
69 | #endif | ||
70 | |||
71 | #endif /* DEBUG */ | ||
72 | |||
73 | |||
50 | #endif /* __XFS_SUPPORT_DEBUG_H__ */ | 74 | #endif /* __XFS_SUPPORT_DEBUG_H__ */ |
diff --git a/fs/xfs/support/move.h b/fs/xfs/support/move.h index 977879c24ff5..324e413deadd 100644 --- a/fs/xfs/support/move.h +++ b/fs/xfs/support/move.h | |||
@@ -55,7 +55,7 @@ enum uio_seg { | |||
55 | }; | 55 | }; |
56 | 56 | ||
57 | struct uio { | 57 | struct uio { |
58 | struct iovec *uio_iov; /* pointer to array of iovecs */ | 58 | struct kvec *uio_iov; /* pointer to array of iovecs */ |
59 | int uio_iovcnt; /* number of iovecs in array */ | 59 | int uio_iovcnt; /* number of iovecs in array */ |
60 | xfs_off_t uio_offset; /* offset in file this uio corresponds to */ | 60 | xfs_off_t uio_offset; /* offset in file this uio corresponds to */ |
61 | int uio_resid; /* residual i/o count */ | 61 | int uio_resid; /* residual i/o count */ |
@@ -63,7 +63,7 @@ struct uio { | |||
63 | }; | 63 | }; |
64 | 64 | ||
65 | typedef struct uio uio_t; | 65 | typedef struct uio uio_t; |
66 | typedef struct iovec iovec_t; | 66 | typedef struct kvec iovec_t; |
67 | 67 | ||
68 | extern int xfs_uio_read (caddr_t, size_t, uio_t *); | 68 | extern int xfs_uio_read (caddr_t, size_t, uio_t *); |
69 | 69 | ||
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 4b0cb474be4c..4ca4beb7bb54 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include "xfs_inode.h" | 31 | #include "xfs_inode.h" |
32 | #include "xfs_btree.h" | 32 | #include "xfs_btree.h" |
33 | #include "xfs_acl.h" | 33 | #include "xfs_acl.h" |
34 | #include "xfs_mac.h" | ||
35 | #include "xfs_attr.h" | 34 | #include "xfs_attr.h" |
36 | 35 | ||
37 | #include <linux/capability.h> | 36 | #include <linux/capability.h> |
diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h index bce81c7a4fdc..5bd1a2c8bd07 100644 --- a/fs/xfs/xfs_alloc_btree.h +++ b/fs/xfs/xfs_alloc_btree.h | |||
@@ -58,7 +58,6 @@ typedef struct xfs_btree_sblock xfs_alloc_block_t; | |||
58 | /* | 58 | /* |
59 | * Real block structures have a size equal to the disk block size. | 59 | * Real block structures have a size equal to the disk block size. |
60 | */ | 60 | */ |
61 | #define XFS_ALLOC_BLOCK_SIZE(lev,cur) (1 << (cur)->bc_blocklog) | ||
62 | #define XFS_ALLOC_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_alloc_mxr[lev != 0]) | 61 | #define XFS_ALLOC_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_alloc_mxr[lev != 0]) |
63 | #define XFS_ALLOC_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_alloc_mnr[lev != 0]) | 62 | #define XFS_ALLOC_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_alloc_mnr[lev != 0]) |
64 | 63 | ||
@@ -87,16 +86,13 @@ typedef struct xfs_btree_sblock xfs_alloc_block_t; | |||
87 | * Record, key, and pointer address macros for btree blocks. | 86 | * Record, key, and pointer address macros for btree blocks. |
88 | */ | 87 | */ |
89 | #define XFS_ALLOC_REC_ADDR(bb,i,cur) \ | 88 | #define XFS_ALLOC_REC_ADDR(bb,i,cur) \ |
90 | XFS_BTREE_REC_ADDR(XFS_ALLOC_BLOCK_SIZE(0,cur), xfs_alloc, \ | 89 | XFS_BTREE_REC_ADDR(xfs_alloc, bb, i) |
91 | bb, i, XFS_ALLOC_BLOCK_MAXRECS(0, cur)) | ||
92 | 90 | ||
93 | #define XFS_ALLOC_KEY_ADDR(bb,i,cur) \ | 91 | #define XFS_ALLOC_KEY_ADDR(bb,i,cur) \ |
94 | XFS_BTREE_KEY_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \ | 92 | XFS_BTREE_KEY_ADDR(xfs_alloc, bb, i) |
95 | bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur)) | ||
96 | 93 | ||
97 | #define XFS_ALLOC_PTR_ADDR(bb,i,cur) \ | 94 | #define XFS_ALLOC_PTR_ADDR(bb,i,cur) \ |
98 | XFS_BTREE_PTR_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \ | 95 | XFS_BTREE_PTR_ADDR(xfs_alloc, bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur)) |
99 | bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur)) | ||
100 | 96 | ||
101 | /* | 97 | /* |
102 | * Decrement cursor by one record at the level. | 98 | * Decrement cursor by one record at the level. |
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 9ada7bdbae52..9d358ffce4e5 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -57,9 +57,9 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | #define ATTR_SYSCOUNT 2 | 59 | #define ATTR_SYSCOUNT 2 |
60 | STATIC struct attrnames posix_acl_access; | 60 | static struct attrnames posix_acl_access; |
61 | STATIC struct attrnames posix_acl_default; | 61 | static struct attrnames posix_acl_default; |
62 | STATIC struct attrnames *attr_system_names[ATTR_SYSCOUNT]; | 62 | static struct attrnames *attr_system_names[ATTR_SYSCOUNT]; |
63 | 63 | ||
64 | /*======================================================================== | 64 | /*======================================================================== |
65 | * Function prototypes for the kernel. | 65 | * Function prototypes for the kernel. |
@@ -199,18 +199,14 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen, | |||
199 | return (error); | 199 | return (error); |
200 | 200 | ||
201 | /* | 201 | /* |
202 | * Determine space new attribute will use, and if it would be | ||
203 | * "local" or "remote" (note: local != inline). | ||
204 | */ | ||
205 | size = xfs_attr_leaf_newentsize(namelen, valuelen, | ||
206 | mp->m_sb.sb_blocksize, &local); | ||
207 | |||
208 | /* | ||
209 | * If the inode doesn't have an attribute fork, add one. | 202 | * If the inode doesn't have an attribute fork, add one. |
210 | * (inode must not be locked when we call this routine) | 203 | * (inode must not be locked when we call this routine) |
211 | */ | 204 | */ |
212 | if (XFS_IFORK_Q(dp) == 0) { | 205 | if (XFS_IFORK_Q(dp) == 0) { |
213 | if ((error = xfs_bmap_add_attrfork(dp, size, rsvd))) | 206 | int sf_size = sizeof(xfs_attr_sf_hdr_t) + |
207 | XFS_ATTR_SF_ENTSIZE_BYNAME(namelen, valuelen); | ||
208 | |||
209 | if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd))) | ||
214 | return(error); | 210 | return(error); |
215 | } | 211 | } |
216 | 212 | ||
@@ -231,6 +227,13 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen, | |||
231 | args.addname = 1; | 227 | args.addname = 1; |
232 | args.oknoent = 1; | 228 | args.oknoent = 1; |
233 | 229 | ||
230 | /* | ||
231 | * Determine space new attribute will use, and if it would be | ||
232 | * "local" or "remote" (note: local != inline). | ||
233 | */ | ||
234 | size = xfs_attr_leaf_newentsize(namelen, valuelen, | ||
235 | mp->m_sb.sb_blocksize, &local); | ||
236 | |||
234 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); | 237 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); |
235 | if (local) { | 238 | if (local) { |
236 | if (size > (mp->m_sb.sb_blocksize >> 1)) { | 239 | if (size > (mp->m_sb.sb_blocksize >> 1)) { |
@@ -346,7 +349,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen, | |||
346 | error = xfs_attr_shortform_to_leaf(&args); | 349 | error = xfs_attr_shortform_to_leaf(&args); |
347 | if (!error) { | 350 | if (!error) { |
348 | error = xfs_bmap_finish(&args.trans, args.flist, | 351 | error = xfs_bmap_finish(&args.trans, args.flist, |
349 | *args.firstblock, &committed); | 352 | &committed); |
350 | } | 353 | } |
351 | if (error) { | 354 | if (error) { |
352 | ASSERT(committed); | 355 | ASSERT(committed); |
@@ -973,7 +976,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
973 | error = xfs_attr_leaf_to_node(args); | 976 | error = xfs_attr_leaf_to_node(args); |
974 | if (!error) { | 977 | if (!error) { |
975 | error = xfs_bmap_finish(&args->trans, args->flist, | 978 | error = xfs_bmap_finish(&args->trans, args->flist, |
976 | *args->firstblock, &committed); | 979 | &committed); |
977 | } | 980 | } |
978 | if (error) { | 981 | if (error) { |
979 | ASSERT(committed); | 982 | ASSERT(committed); |
@@ -1074,7 +1077,6 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
1074 | if (!error) { | 1077 | if (!error) { |
1075 | error = xfs_bmap_finish(&args->trans, | 1078 | error = xfs_bmap_finish(&args->trans, |
1076 | args->flist, | 1079 | args->flist, |
1077 | *args->firstblock, | ||
1078 | &committed); | 1080 | &committed); |
1079 | } | 1081 | } |
1080 | if (error) { | 1082 | if (error) { |
@@ -1152,7 +1154,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) | |||
1152 | /* bp is gone due to xfs_da_shrink_inode */ | 1154 | /* bp is gone due to xfs_da_shrink_inode */ |
1153 | if (!error) { | 1155 | if (!error) { |
1154 | error = xfs_bmap_finish(&args->trans, args->flist, | 1156 | error = xfs_bmap_finish(&args->trans, args->flist, |
1155 | *args->firstblock, &committed); | 1157 | &committed); |
1156 | } | 1158 | } |
1157 | if (error) { | 1159 | if (error) { |
1158 | ASSERT(committed); | 1160 | ASSERT(committed); |
@@ -1307,7 +1309,6 @@ restart: | |||
1307 | if (!error) { | 1309 | if (!error) { |
1308 | error = xfs_bmap_finish(&args->trans, | 1310 | error = xfs_bmap_finish(&args->trans, |
1309 | args->flist, | 1311 | args->flist, |
1310 | *args->firstblock, | ||
1311 | &committed); | 1312 | &committed); |
1312 | } | 1313 | } |
1313 | if (error) { | 1314 | if (error) { |
@@ -1347,7 +1348,7 @@ restart: | |||
1347 | error = xfs_da_split(state); | 1348 | error = xfs_da_split(state); |
1348 | if (!error) { | 1349 | if (!error) { |
1349 | error = xfs_bmap_finish(&args->trans, args->flist, | 1350 | error = xfs_bmap_finish(&args->trans, args->flist, |
1350 | *args->firstblock, &committed); | 1351 | &committed); |
1351 | } | 1352 | } |
1352 | if (error) { | 1353 | if (error) { |
1353 | ASSERT(committed); | 1354 | ASSERT(committed); |
@@ -1459,7 +1460,6 @@ restart: | |||
1459 | if (!error) { | 1460 | if (!error) { |
1460 | error = xfs_bmap_finish(&args->trans, | 1461 | error = xfs_bmap_finish(&args->trans, |
1461 | args->flist, | 1462 | args->flist, |
1462 | *args->firstblock, | ||
1463 | &committed); | 1463 | &committed); |
1464 | } | 1464 | } |
1465 | if (error) { | 1465 | if (error) { |
@@ -1594,7 +1594,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1594 | error = xfs_da_join(state); | 1594 | error = xfs_da_join(state); |
1595 | if (!error) { | 1595 | if (!error) { |
1596 | error = xfs_bmap_finish(&args->trans, args->flist, | 1596 | error = xfs_bmap_finish(&args->trans, args->flist, |
1597 | *args->firstblock, &committed); | 1597 | &committed); |
1598 | } | 1598 | } |
1599 | if (error) { | 1599 | if (error) { |
1600 | ASSERT(committed); | 1600 | ASSERT(committed); |
@@ -1646,7 +1646,6 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1646 | if (!error) { | 1646 | if (!error) { |
1647 | error = xfs_bmap_finish(&args->trans, | 1647 | error = xfs_bmap_finish(&args->trans, |
1648 | args->flist, | 1648 | args->flist, |
1649 | *args->firstblock, | ||
1650 | &committed); | 1649 | &committed); |
1651 | } | 1650 | } |
1652 | if (error) { | 1651 | if (error) { |
@@ -2090,7 +2089,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2090 | args->flist, NULL); | 2089 | args->flist, NULL); |
2091 | if (!error) { | 2090 | if (!error) { |
2092 | error = xfs_bmap_finish(&args->trans, args->flist, | 2091 | error = xfs_bmap_finish(&args->trans, args->flist, |
2093 | *args->firstblock, &committed); | 2092 | &committed); |
2094 | } | 2093 | } |
2095 | if (error) { | 2094 | if (error) { |
2096 | ASSERT(committed); | 2095 | ASSERT(committed); |
@@ -2246,7 +2245,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
2246 | NULL, &done); | 2245 | NULL, &done); |
2247 | if (!error) { | 2246 | if (!error) { |
2248 | error = xfs_bmap_finish(&args->trans, args->flist, | 2247 | error = xfs_bmap_finish(&args->trans, args->flist, |
2249 | *args->firstblock, &committed); | 2248 | &committed); |
2250 | } | 2249 | } |
2251 | if (error) { | 2250 | if (error) { |
2252 | ASSERT(committed); | 2251 | ASSERT(committed); |
@@ -2477,7 +2476,7 @@ posix_acl_default_exists( | |||
2477 | return xfs_acl_vhasacl_default(vp); | 2476 | return xfs_acl_vhasacl_default(vp); |
2478 | } | 2477 | } |
2479 | 2478 | ||
2480 | STATIC struct attrnames posix_acl_access = { | 2479 | static struct attrnames posix_acl_access = { |
2481 | .attr_name = "posix_acl_access", | 2480 | .attr_name = "posix_acl_access", |
2482 | .attr_namelen = sizeof("posix_acl_access") - 1, | 2481 | .attr_namelen = sizeof("posix_acl_access") - 1, |
2483 | .attr_get = posix_acl_access_get, | 2482 | .attr_get = posix_acl_access_get, |
@@ -2486,7 +2485,7 @@ STATIC struct attrnames posix_acl_access = { | |||
2486 | .attr_exists = posix_acl_access_exists, | 2485 | .attr_exists = posix_acl_access_exists, |
2487 | }; | 2486 | }; |
2488 | 2487 | ||
2489 | STATIC struct attrnames posix_acl_default = { | 2488 | static struct attrnames posix_acl_default = { |
2490 | .attr_name = "posix_acl_default", | 2489 | .attr_name = "posix_acl_default", |
2491 | .attr_namelen = sizeof("posix_acl_default") - 1, | 2490 | .attr_namelen = sizeof("posix_acl_default") - 1, |
2492 | .attr_get = posix_acl_default_get, | 2491 | .attr_get = posix_acl_default_get, |
@@ -2495,7 +2494,7 @@ STATIC struct attrnames posix_acl_default = { | |||
2495 | .attr_exists = posix_acl_default_exists, | 2494 | .attr_exists = posix_acl_default_exists, |
2496 | }; | 2495 | }; |
2497 | 2496 | ||
2498 | STATIC struct attrnames *attr_system_names[] = | 2497 | static struct attrnames *attr_system_names[] = |
2499 | { &posix_acl_access, &posix_acl_default }; | 2498 | { &posix_acl_access, &posix_acl_default }; |
2500 | 2499 | ||
2501 | 2500 | ||
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 9719bbef122c..8eab73e8340a 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -94,7 +94,7 @@ STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); | |||
94 | * Namespace helper routines | 94 | * Namespace helper routines |
95 | *========================================================================*/ | 95 | *========================================================================*/ |
96 | 96 | ||
97 | STATIC inline attrnames_t * | 97 | STATIC_INLINE attrnames_t * |
98 | xfs_attr_flags_namesp(int flags) | 98 | xfs_attr_flags_namesp(int flags) |
99 | { | 99 | { |
100 | return ((flags & XFS_ATTR_SECURE) ? &attr_secure: | 100 | return ((flags & XFS_ATTR_SECURE) ? &attr_secure: |
@@ -105,7 +105,7 @@ xfs_attr_flags_namesp(int flags) | |||
105 | * If namespace bits don't match return 0. | 105 | * If namespace bits don't match return 0. |
106 | * If all match then return 1. | 106 | * If all match then return 1. |
107 | */ | 107 | */ |
108 | STATIC inline int | 108 | STATIC_INLINE int |
109 | xfs_attr_namesp_match(int arg_flags, int ondisk_flags) | 109 | xfs_attr_namesp_match(int arg_flags, int ondisk_flags) |
110 | { | 110 | { |
111 | return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags); | 111 | return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags); |
@@ -116,7 +116,7 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags) | |||
116 | * then return 0. | 116 | * then return 0. |
117 | * If all match or are overridable then return 1. | 117 | * If all match or are overridable then return 1. |
118 | */ | 118 | */ |
119 | STATIC inline int | 119 | STATIC_INLINE int |
120 | xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags) | 120 | xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags) |
121 | { | 121 | { |
122 | if (((arg_flags & ATTR_SECURE) == 0) != | 122 | if (((arg_flags & ATTR_SECURE) == 0) != |
@@ -150,6 +150,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) | |||
150 | int offset; | 150 | int offset; |
151 | int minforkoff; /* lower limit on valid forkoff locations */ | 151 | int minforkoff; /* lower limit on valid forkoff locations */ |
152 | int maxforkoff; /* upper limit on valid forkoff locations */ | 152 | int maxforkoff; /* upper limit on valid forkoff locations */ |
153 | int dsize; | ||
153 | xfs_mount_t *mp = dp->i_mount; | 154 | xfs_mount_t *mp = dp->i_mount; |
154 | 155 | ||
155 | offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ | 156 | offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ |
@@ -169,8 +170,43 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) | |||
169 | return 0; | 170 | return 0; |
170 | } | 171 | } |
171 | 172 | ||
172 | /* data fork btree root can have at least this many key/ptr pairs */ | 173 | dsize = dp->i_df.if_bytes; |
173 | minforkoff = MAX(dp->i_df.if_bytes, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); | 174 | |
175 | switch (dp->i_d.di_format) { | ||
176 | case XFS_DINODE_FMT_EXTENTS: | ||
177 | /* | ||
178 | * If there is no attr fork and the data fork is extents, | ||
179 | * determine if creating the default attr fork will result | ||
180 | * in the extents form migrating to btree. If so, the | ||
181 | * minimum offset only needs to be the space required for | ||
182 | * the btree root. | ||
183 | */ | ||
184 | if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > mp->m_attroffset) | ||
185 | dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); | ||
186 | break; | ||
187 | |||
188 | case XFS_DINODE_FMT_BTREE: | ||
189 | /* | ||
190 | * If have data btree then keep forkoff if we have one, | ||
191 | * otherwise we are adding a new attr, so then we set | ||
192 | * minforkoff to where the btree root can finish so we have | ||
193 | * plenty of room for attrs | ||
194 | */ | ||
195 | if (dp->i_d.di_forkoff) { | ||
196 | if (offset < dp->i_d.di_forkoff) | ||
197 | return 0; | ||
198 | else | ||
199 | return dp->i_d.di_forkoff; | ||
200 | } else | ||
201 | dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot); | ||
202 | break; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * A data fork btree root must have space for at least | ||
207 | * MINDBTPTRS key/ptr pairs if the data fork is small or empty. | ||
208 | */ | ||
209 | minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); | ||
174 | minforkoff = roundup(minforkoff, 8) >> 3; | 210 | minforkoff = roundup(minforkoff, 8) >> 3; |
175 | 211 | ||
176 | /* attr fork btree root can have at least this many key/ptr pairs */ | 212 | /* attr fork btree root can have at least this many key/ptr pairs */ |
@@ -336,7 +372,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
336 | */ | 372 | */ |
337 | totsize -= size; | 373 | totsize -= size; |
338 | if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname && | 374 | if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname && |
339 | (mp->m_flags & XFS_MOUNT_ATTR2)) { | 375 | (mp->m_flags & XFS_MOUNT_ATTR2) && |
376 | (dp->i_d.di_format != XFS_DINODE_FMT_BTREE)) { | ||
340 | /* | 377 | /* |
341 | * Last attribute now removed, revert to original | 378 | * Last attribute now removed, revert to original |
342 | * inode format making all literal area available | 379 | * inode format making all literal area available |
@@ -355,7 +392,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
355 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); | 392 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); |
356 | ASSERT(dp->i_d.di_forkoff); | 393 | ASSERT(dp->i_d.di_forkoff); |
357 | ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname || | 394 | ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname || |
358 | !(mp->m_flags & XFS_MOUNT_ATTR2)); | 395 | !(mp->m_flags & XFS_MOUNT_ATTR2) || |
396 | dp->i_d.di_format == XFS_DINODE_FMT_BTREE); | ||
359 | dp->i_afp->if_ext_max = | 397 | dp->i_afp->if_ext_max = |
360 | XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | 398 | XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); |
361 | dp->i_df.if_ext_max = | 399 | dp->i_df.if_ext_max = |
@@ -748,6 +786,7 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) | |||
748 | + be16_to_cpu(name_loc->valuelen); | 786 | + be16_to_cpu(name_loc->valuelen); |
749 | } | 787 | } |
750 | if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && | 788 | if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) && |
789 | (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && | ||
751 | (bytes == sizeof(struct xfs_attr_sf_hdr))) | 790 | (bytes == sizeof(struct xfs_attr_sf_hdr))) |
752 | return(-1); | 791 | return(-1); |
753 | return(xfs_attr_shortform_bytesfit(dp, bytes)); | 792 | return(xfs_attr_shortform_bytesfit(dp, bytes)); |
@@ -786,6 +825,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) | |||
786 | 825 | ||
787 | if (forkoff == -1) { | 826 | if (forkoff == -1) { |
788 | ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); | 827 | ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); |
828 | ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); | ||
789 | 829 | ||
790 | /* | 830 | /* |
791 | * Last attribute was removed, revert to original | 831 | * Last attribute was removed, revert to original |
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c index 43be6a7e47c6..1afe07f67e3b 100644 --- a/fs/xfs/xfs_bit.c +++ b/fs/xfs/xfs_bit.c | |||
@@ -29,7 +29,7 @@ | |||
29 | /* | 29 | /* |
30 | * Index of high bit number in byte, -1 for none set, 0..7 otherwise. | 30 | * Index of high bit number in byte, -1 for none set, 0..7 otherwise. |
31 | */ | 31 | */ |
32 | STATIC const char xfs_highbit[256] = { | 32 | static const char xfs_highbit[256] = { |
33 | -1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */ | 33 | -1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */ |
34 | 3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */ | 34 | 3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */ |
35 | 4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */ | 35 | 4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */ |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 498ad50d1f45..87795188cedf 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -185,16 +185,6 @@ xfs_bmap_btree_to_extents( | |||
185 | int *logflagsp, /* inode logging flags */ | 185 | int *logflagsp, /* inode logging flags */ |
186 | int whichfork); /* data or attr fork */ | 186 | int whichfork); /* data or attr fork */ |
187 | 187 | ||
188 | #ifdef DEBUG | ||
189 | /* | ||
190 | * Check that the extents list for the inode ip is in the right order. | ||
191 | */ | ||
192 | STATIC void | ||
193 | xfs_bmap_check_extents( | ||
194 | xfs_inode_t *ip, /* incore inode pointer */ | ||
195 | int whichfork); /* data or attr fork */ | ||
196 | #endif | ||
197 | |||
198 | /* | 188 | /* |
199 | * Called by xfs_bmapi to update file extent records and the btree | 189 | * Called by xfs_bmapi to update file extent records and the btree |
200 | * after removing space (or undoing a delayed allocation). | 190 | * after removing space (or undoing a delayed allocation). |
@@ -410,7 +400,6 @@ xfs_bmap_count_leaves( | |||
410 | STATIC int | 400 | STATIC int |
411 | xfs_bmap_disk_count_leaves( | 401 | xfs_bmap_disk_count_leaves( |
412 | xfs_ifork_t *ifp, | 402 | xfs_ifork_t *ifp, |
413 | xfs_mount_t *mp, | ||
414 | xfs_extnum_t idx, | 403 | xfs_extnum_t idx, |
415 | xfs_bmbt_block_t *block, | 404 | xfs_bmbt_block_t *block, |
416 | int numrecs, | 405 | int numrecs, |
@@ -684,7 +673,7 @@ xfs_bmap_add_extent( | |||
684 | ASSERT(nblks <= da_old); | 673 | ASSERT(nblks <= da_old); |
685 | if (nblks < da_old) | 674 | if (nblks < da_old) |
686 | xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, | 675 | xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, |
687 | (int)(da_old - nblks), rsvd); | 676 | (int64_t)(da_old - nblks), rsvd); |
688 | } | 677 | } |
689 | /* | 678 | /* |
690 | * Clear out the allocated field, done with it now in any case. | 679 | * Clear out the allocated field, done with it now in any case. |
@@ -1209,7 +1198,7 @@ xfs_bmap_add_extent_delay_real( | |||
1209 | diff = (int)(temp + temp2 - STARTBLOCKVAL(PREV.br_startblock) - | 1198 | diff = (int)(temp + temp2 - STARTBLOCKVAL(PREV.br_startblock) - |
1210 | (cur ? cur->bc_private.b.allocated : 0)); | 1199 | (cur ? cur->bc_private.b.allocated : 0)); |
1211 | if (diff > 0 && | 1200 | if (diff > 0 && |
1212 | xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -diff, rsvd)) { | 1201 | xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) { |
1213 | /* | 1202 | /* |
1214 | * Ick gross gag me with a spoon. | 1203 | * Ick gross gag me with a spoon. |
1215 | */ | 1204 | */ |
@@ -1220,7 +1209,7 @@ xfs_bmap_add_extent_delay_real( | |||
1220 | diff--; | 1209 | diff--; |
1221 | if (!diff || | 1210 | if (!diff || |
1222 | !xfs_mod_incore_sb(ip->i_mount, | 1211 | !xfs_mod_incore_sb(ip->i_mount, |
1223 | XFS_SBS_FDBLOCKS, -diff, rsvd)) | 1212 | XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) |
1224 | break; | 1213 | break; |
1225 | } | 1214 | } |
1226 | if (temp2) { | 1215 | if (temp2) { |
@@ -1228,7 +1217,7 @@ xfs_bmap_add_extent_delay_real( | |||
1228 | diff--; | 1217 | diff--; |
1229 | if (!diff || | 1218 | if (!diff || |
1230 | !xfs_mod_incore_sb(ip->i_mount, | 1219 | !xfs_mod_incore_sb(ip->i_mount, |
1231 | XFS_SBS_FDBLOCKS, -diff, rsvd)) | 1220 | XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) |
1232 | break; | 1221 | break; |
1233 | } | 1222 | } |
1234 | } | 1223 | } |
@@ -2015,7 +2004,7 @@ xfs_bmap_add_extent_hole_delay( | |||
2015 | if (oldlen != newlen) { | 2004 | if (oldlen != newlen) { |
2016 | ASSERT(oldlen > newlen); | 2005 | ASSERT(oldlen > newlen); |
2017 | xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, | 2006 | xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, |
2018 | (int)(oldlen - newlen), rsvd); | 2007 | (int64_t)(oldlen - newlen), rsvd); |
2019 | /* | 2008 | /* |
2020 | * Nothing to do for disk quota accounting here. | 2009 | * Nothing to do for disk quota accounting here. |
2021 | */ | 2010 | */ |
@@ -3359,7 +3348,7 @@ xfs_bmap_del_extent( | |||
3359 | */ | 3348 | */ |
3360 | ASSERT(da_old >= da_new); | 3349 | ASSERT(da_old >= da_new); |
3361 | if (da_old > da_new) | 3350 | if (da_old > da_new) |
3362 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new), | 3351 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new), |
3363 | rsvd); | 3352 | rsvd); |
3364 | if (delta) { | 3353 | if (delta) { |
3365 | /* DELTA: report the original extent. */ | 3354 | /* DELTA: report the original extent. */ |
@@ -3543,6 +3532,7 @@ xfs_bmap_forkoff_reset( | |||
3543 | if (whichfork == XFS_ATTR_FORK && | 3532 | if (whichfork == XFS_ATTR_FORK && |
3544 | (ip->i_d.di_format != XFS_DINODE_FMT_DEV) && | 3533 | (ip->i_d.di_format != XFS_DINODE_FMT_DEV) && |
3545 | (ip->i_d.di_format != XFS_DINODE_FMT_UUID) && | 3534 | (ip->i_d.di_format != XFS_DINODE_FMT_UUID) && |
3535 | (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) && | ||
3546 | ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) { | 3536 | ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) { |
3547 | ip->i_d.di_forkoff = mp->m_attroffset >> 3; | 3537 | ip->i_d.di_forkoff = mp->m_attroffset >> 3; |
3548 | ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) / | 3538 | ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) / |
@@ -4079,7 +4069,7 @@ xfs_bmap_add_attrfork( | |||
4079 | } else | 4069 | } else |
4080 | XFS_SB_UNLOCK(mp, s); | 4070 | XFS_SB_UNLOCK(mp, s); |
4081 | } | 4071 | } |
4082 | if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) | 4072 | if ((error = xfs_bmap_finish(&tp, &flist, &committed))) |
4083 | goto error2; | 4073 | goto error2; |
4084 | error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES, NULL); | 4074 | error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES, NULL); |
4085 | ASSERT(ip->i_df.if_ext_max == | 4075 | ASSERT(ip->i_df.if_ext_max == |
@@ -4212,7 +4202,6 @@ int /* error */ | |||
4212 | xfs_bmap_finish( | 4202 | xfs_bmap_finish( |
4213 | xfs_trans_t **tp, /* transaction pointer addr */ | 4203 | xfs_trans_t **tp, /* transaction pointer addr */ |
4214 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | 4204 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ |
4215 | xfs_fsblock_t firstblock, /* controlled ag for allocs */ | ||
4216 | int *committed) /* xact committed or not */ | 4205 | int *committed) /* xact committed or not */ |
4217 | { | 4206 | { |
4218 | xfs_efd_log_item_t *efd; /* extent free data */ | 4207 | xfs_efd_log_item_t *efd; /* extent free data */ |
@@ -4533,8 +4522,7 @@ xfs_bmap_read_extents( | |||
4533 | error0); | 4522 | error0); |
4534 | if (level == 0) | 4523 | if (level == 0) |
4535 | break; | 4524 | break; |
4536 | pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block, | 4525 | pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]); |
4537 | 1, mp->m_bmap_dmxr[1]); | ||
4538 | bno = be64_to_cpu(*pp); | 4526 | bno = be64_to_cpu(*pp); |
4539 | XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0); | 4527 | XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0); |
4540 | xfs_trans_brelse(tp, bp); | 4528 | xfs_trans_brelse(tp, bp); |
@@ -4577,8 +4565,7 @@ xfs_bmap_read_extents( | |||
4577 | /* | 4565 | /* |
4578 | * Copy records into the extent records. | 4566 | * Copy records into the extent records. |
4579 | */ | 4567 | */ |
4580 | frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, | 4568 | frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1); |
4581 | block, 1, mp->m_bmap_dmxr[0]); | ||
4582 | start = i; | 4569 | start = i; |
4583 | for (j = 0; j < num_recs; j++, i++, frp++) { | 4570 | for (j = 0; j < num_recs; j++, i++, frp++) { |
4584 | trp = xfs_iext_get_ext(ifp, i); | 4571 | trp = xfs_iext_get_ext(ifp, i); |
@@ -4929,28 +4916,28 @@ xfs_bmapi( | |||
4929 | if (rt) { | 4916 | if (rt) { |
4930 | error = xfs_mod_incore_sb(mp, | 4917 | error = xfs_mod_incore_sb(mp, |
4931 | XFS_SBS_FREXTENTS, | 4918 | XFS_SBS_FREXTENTS, |
4932 | -(extsz), (flags & | 4919 | -((int64_t)extsz), (flags & |
4933 | XFS_BMAPI_RSVBLOCKS)); | 4920 | XFS_BMAPI_RSVBLOCKS)); |
4934 | } else { | 4921 | } else { |
4935 | error = xfs_mod_incore_sb(mp, | 4922 | error = xfs_mod_incore_sb(mp, |
4936 | XFS_SBS_FDBLOCKS, | 4923 | XFS_SBS_FDBLOCKS, |
4937 | -(alen), (flags & | 4924 | -((int64_t)alen), (flags & |
4938 | XFS_BMAPI_RSVBLOCKS)); | 4925 | XFS_BMAPI_RSVBLOCKS)); |
4939 | } | 4926 | } |
4940 | if (!error) { | 4927 | if (!error) { |
4941 | error = xfs_mod_incore_sb(mp, | 4928 | error = xfs_mod_incore_sb(mp, |
4942 | XFS_SBS_FDBLOCKS, | 4929 | XFS_SBS_FDBLOCKS, |
4943 | -(indlen), (flags & | 4930 | -((int64_t)indlen), (flags & |
4944 | XFS_BMAPI_RSVBLOCKS)); | 4931 | XFS_BMAPI_RSVBLOCKS)); |
4945 | if (error && rt) | 4932 | if (error && rt) |
4946 | xfs_mod_incore_sb(mp, | 4933 | xfs_mod_incore_sb(mp, |
4947 | XFS_SBS_FREXTENTS, | 4934 | XFS_SBS_FREXTENTS, |
4948 | extsz, (flags & | 4935 | (int64_t)extsz, (flags & |
4949 | XFS_BMAPI_RSVBLOCKS)); | 4936 | XFS_BMAPI_RSVBLOCKS)); |
4950 | else if (error) | 4937 | else if (error) |
4951 | xfs_mod_incore_sb(mp, | 4938 | xfs_mod_incore_sb(mp, |
4952 | XFS_SBS_FDBLOCKS, | 4939 | XFS_SBS_FDBLOCKS, |
4953 | alen, (flags & | 4940 | (int64_t)alen, (flags & |
4954 | XFS_BMAPI_RSVBLOCKS)); | 4941 | XFS_BMAPI_RSVBLOCKS)); |
4955 | } | 4942 | } |
4956 | 4943 | ||
@@ -5616,13 +5603,13 @@ xfs_bunmapi( | |||
5616 | rtexts = XFS_FSB_TO_B(mp, del.br_blockcount); | 5603 | rtexts = XFS_FSB_TO_B(mp, del.br_blockcount); |
5617 | do_div(rtexts, mp->m_sb.sb_rextsize); | 5604 | do_div(rtexts, mp->m_sb.sb_rextsize); |
5618 | xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, | 5605 | xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, |
5619 | (int)rtexts, rsvd); | 5606 | (int64_t)rtexts, rsvd); |
5620 | (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, | 5607 | (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, |
5621 | NULL, ip, -((long)del.br_blockcount), 0, | 5608 | NULL, ip, -((long)del.br_blockcount), 0, |
5622 | XFS_QMOPT_RES_RTBLKS); | 5609 | XFS_QMOPT_RES_RTBLKS); |
5623 | } else { | 5610 | } else { |
5624 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, | 5611 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, |
5625 | (int)del.br_blockcount, rsvd); | 5612 | (int64_t)del.br_blockcount, rsvd); |
5626 | (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, | 5613 | (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, |
5627 | NULL, ip, -((long)del.br_blockcount), 0, | 5614 | NULL, ip, -((long)del.br_blockcount), 0, |
5628 | XFS_QMOPT_RES_REGBLKS); | 5615 | XFS_QMOPT_RES_REGBLKS); |
@@ -6048,32 +6035,6 @@ xfs_bmap_eof( | |||
6048 | } | 6035 | } |
6049 | 6036 | ||
6050 | #ifdef DEBUG | 6037 | #ifdef DEBUG |
6051 | /* | ||
6052 | * Check that the extents list for the inode ip is in the right order. | ||
6053 | */ | ||
6054 | STATIC void | ||
6055 | xfs_bmap_check_extents( | ||
6056 | xfs_inode_t *ip, /* incore inode pointer */ | ||
6057 | int whichfork) /* data or attr fork */ | ||
6058 | { | ||
6059 | xfs_bmbt_rec_t *ep; /* current extent entry */ | ||
6060 | xfs_extnum_t idx; /* extent record index */ | ||
6061 | xfs_ifork_t *ifp; /* inode fork pointer */ | ||
6062 | xfs_extnum_t nextents; /* number of extents in list */ | ||
6063 | xfs_bmbt_rec_t *nextp; /* next extent entry */ | ||
6064 | |||
6065 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
6066 | ASSERT(ifp->if_flags & XFS_IFEXTENTS); | ||
6067 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
6068 | ep = xfs_iext_get_ext(ifp, 0); | ||
6069 | for (idx = 0; idx < nextents - 1; idx++) { | ||
6070 | nextp = xfs_iext_get_ext(ifp, idx + 1); | ||
6071 | xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep, | ||
6072 | (void *)(nextp)); | ||
6073 | ep = nextp; | ||
6074 | } | ||
6075 | } | ||
6076 | |||
6077 | STATIC | 6038 | STATIC |
6078 | xfs_buf_t * | 6039 | xfs_buf_t * |
6079 | xfs_bmap_get_bp( | 6040 | xfs_bmap_get_bp( |
@@ -6156,8 +6117,7 @@ xfs_check_block( | |||
6156 | if (root) { | 6117 | if (root) { |
6157 | keyp = XFS_BMAP_BROOT_KEY_ADDR(block, i, sz); | 6118 | keyp = XFS_BMAP_BROOT_KEY_ADDR(block, i, sz); |
6158 | } else { | 6119 | } else { |
6159 | keyp = XFS_BTREE_KEY_ADDR(mp->m_sb.sb_blocksize, | 6120 | keyp = XFS_BTREE_KEY_ADDR(xfs_bmbt, block, i); |
6160 | xfs_bmbt, block, i, dmxr); | ||
6161 | } | 6121 | } |
6162 | 6122 | ||
6163 | if (prevp) { | 6123 | if (prevp) { |
@@ -6172,15 +6132,14 @@ xfs_check_block( | |||
6172 | if (root) { | 6132 | if (root) { |
6173 | pp = XFS_BMAP_BROOT_PTR_ADDR(block, i, sz); | 6133 | pp = XFS_BMAP_BROOT_PTR_ADDR(block, i, sz); |
6174 | } else { | 6134 | } else { |
6175 | pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, | 6135 | pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, i, dmxr); |
6176 | xfs_bmbt, block, i, dmxr); | ||
6177 | } | 6136 | } |
6178 | for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) { | 6137 | for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) { |
6179 | if (root) { | 6138 | if (root) { |
6180 | thispa = XFS_BMAP_BROOT_PTR_ADDR(block, j, sz); | 6139 | thispa = XFS_BMAP_BROOT_PTR_ADDR(block, j, sz); |
6181 | } else { | 6140 | } else { |
6182 | thispa = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, | 6141 | thispa = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, j, |
6183 | xfs_bmbt, block, j, dmxr); | 6142 | dmxr); |
6184 | } | 6143 | } |
6185 | if (*thispa == *pp) { | 6144 | if (*thispa == *pp) { |
6186 | cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld", | 6145 | cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld", |
@@ -6267,8 +6226,7 @@ xfs_bmap_check_leaf_extents( | |||
6267 | */ | 6226 | */ |
6268 | 6227 | ||
6269 | xfs_check_block(block, mp, 0, 0); | 6228 | xfs_check_block(block, mp, 0, 0); |
6270 | pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block, | 6229 | pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]); |
6271 | 1, mp->m_bmap_dmxr[1]); | ||
6272 | bno = be64_to_cpu(*pp); | 6230 | bno = be64_to_cpu(*pp); |
6273 | XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0); | 6231 | XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0); |
6274 | if (bp_release) { | 6232 | if (bp_release) { |
@@ -6305,11 +6263,9 @@ xfs_bmap_check_leaf_extents( | |||
6305 | * conform with the first entry in this one. | 6263 | * conform with the first entry in this one. |
6306 | */ | 6264 | */ |
6307 | 6265 | ||
6308 | ep = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, | 6266 | ep = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1); |
6309 | block, 1, mp->m_bmap_dmxr[0]); | ||
6310 | for (j = 1; j < num_recs; j++) { | 6267 | for (j = 1; j < num_recs; j++) { |
6311 | nextp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, | 6268 | nextp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, j + 1); |
6312 | block, j + 1, mp->m_bmap_dmxr[0]); | ||
6313 | if (lastp) { | 6269 | if (lastp) { |
6314 | xfs_btree_check_rec(XFS_BTNUM_BMAP, | 6270 | xfs_btree_check_rec(XFS_BTNUM_BMAP, |
6315 | (void *)lastp, (void *)ep); | 6271 | (void *)lastp, (void *)ep); |
@@ -6454,8 +6410,7 @@ xfs_bmap_count_tree( | |||
6454 | } | 6410 | } |
6455 | 6411 | ||
6456 | /* Dive to the next level */ | 6412 | /* Dive to the next level */ |
6457 | pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, | 6413 | pp = XFS_BTREE_PTR_ADDR(xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]); |
6458 | xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]); | ||
6459 | bno = be64_to_cpu(*pp); | 6414 | bno = be64_to_cpu(*pp); |
6460 | if (unlikely((error = | 6415 | if (unlikely((error = |
6461 | xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) { | 6416 | xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) { |
@@ -6470,7 +6425,7 @@ xfs_bmap_count_tree( | |||
6470 | for (;;) { | 6425 | for (;;) { |
6471 | nextbno = be64_to_cpu(block->bb_rightsib); | 6426 | nextbno = be64_to_cpu(block->bb_rightsib); |
6472 | numrecs = be16_to_cpu(block->bb_numrecs); | 6427 | numrecs = be16_to_cpu(block->bb_numrecs); |
6473 | if (unlikely(xfs_bmap_disk_count_leaves(ifp, mp, | 6428 | if (unlikely(xfs_bmap_disk_count_leaves(ifp, |
6474 | 0, block, numrecs, count) < 0)) { | 6429 | 0, block, numrecs, count) < 0)) { |
6475 | xfs_trans_brelse(tp, bp); | 6430 | xfs_trans_brelse(tp, bp); |
6476 | XFS_ERROR_REPORT("xfs_bmap_count_tree(2)", | 6431 | XFS_ERROR_REPORT("xfs_bmap_count_tree(2)", |
@@ -6518,7 +6473,6 @@ xfs_bmap_count_leaves( | |||
6518 | int | 6473 | int |
6519 | xfs_bmap_disk_count_leaves( | 6474 | xfs_bmap_disk_count_leaves( |
6520 | xfs_ifork_t *ifp, | 6475 | xfs_ifork_t *ifp, |
6521 | xfs_mount_t *mp, | ||
6522 | xfs_extnum_t idx, | 6476 | xfs_extnum_t idx, |
6523 | xfs_bmbt_block_t *block, | 6477 | xfs_bmbt_block_t *block, |
6524 | int numrecs, | 6478 | int numrecs, |
@@ -6528,8 +6482,7 @@ xfs_bmap_disk_count_leaves( | |||
6528 | xfs_bmbt_rec_t *frp; | 6482 | xfs_bmbt_rec_t *frp; |
6529 | 6483 | ||
6530 | for (b = 1; b <= numrecs; b++) { | 6484 | for (b = 1; b <= numrecs; b++) { |
6531 | frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, | 6485 | frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, idx + b); |
6532 | xfs_bmbt, block, idx + b, mp->m_bmap_dmxr[0]); | ||
6533 | *count += xfs_bmbt_disk_get_blockcount(frp); | 6486 | *count += xfs_bmbt_disk_get_blockcount(frp); |
6534 | } | 6487 | } |
6535 | return 0; | 6488 | return 0; |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 80e93409b78d..4f24c7e39b31 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -202,7 +202,6 @@ int /* error */ | |||
202 | xfs_bmap_finish( | 202 | xfs_bmap_finish( |
203 | struct xfs_trans **tp, /* transaction pointer addr */ | 203 | struct xfs_trans **tp, /* transaction pointer addr */ |
204 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | 204 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ |
205 | xfs_fsblock_t firstblock, /* controlled a.g. for allocs */ | ||
206 | int *committed); /* xact committed or not */ | 205 | int *committed); /* xact committed or not */ |
207 | 206 | ||
208 | /* | 207 | /* |
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index a7b835bf870a..0bf192fea3eb 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c | |||
@@ -678,47 +678,6 @@ error0: | |||
678 | return error; | 678 | return error; |
679 | } | 679 | } |
680 | 680 | ||
681 | #ifdef DEBUG | ||
682 | /* | ||
683 | * Get the data from the pointed-to record. | ||
684 | */ | ||
685 | int | ||
686 | xfs_bmbt_get_rec( | ||
687 | xfs_btree_cur_t *cur, | ||
688 | xfs_fileoff_t *off, | ||
689 | xfs_fsblock_t *bno, | ||
690 | xfs_filblks_t *len, | ||
691 | xfs_exntst_t *state, | ||
692 | int *stat) | ||
693 | { | ||
694 | xfs_bmbt_block_t *block; | ||
695 | xfs_buf_t *bp; | ||
696 | #ifdef DEBUG | ||
697 | int error; | ||
698 | #endif | ||
699 | int ptr; | ||
700 | xfs_bmbt_rec_t *rp; | ||
701 | |||
702 | block = xfs_bmbt_get_block(cur, 0, &bp); | ||
703 | ptr = cur->bc_ptrs[0]; | ||
704 | #ifdef DEBUG | ||
705 | if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) | ||
706 | return error; | ||
707 | #endif | ||
708 | if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) { | ||
709 | *stat = 0; | ||
710 | return 0; | ||
711 | } | ||
712 | rp = XFS_BMAP_REC_IADDR(block, ptr, cur); | ||
713 | *off = xfs_bmbt_disk_get_startoff(rp); | ||
714 | *bno = xfs_bmbt_disk_get_startblock(rp); | ||
715 | *len = xfs_bmbt_disk_get_blockcount(rp); | ||
716 | *state = xfs_bmbt_disk_get_state(rp); | ||
717 | *stat = 1; | ||
718 | return 0; | ||
719 | } | ||
720 | #endif | ||
721 | |||
722 | /* | 681 | /* |
723 | * Insert one record/level. Return information to the caller | 682 | * Insert one record/level. Return information to the caller |
724 | * allowing the next level up to proceed if necessary. | 683 | * allowing the next level up to proceed if necessary. |
@@ -1731,9 +1690,9 @@ xfs_bmdr_to_bmbt( | |||
1731 | rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO); | 1690 | rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO); |
1732 | rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO); | 1691 | rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO); |
1733 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); | 1692 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); |
1734 | fkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); | 1693 | fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); |
1735 | tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); | 1694 | tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); |
1736 | fpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); | 1695 | fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); |
1737 | tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); | 1696 | tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); |
1738 | dmxr = be16_to_cpu(dblock->bb_numrecs); | 1697 | dmxr = be16_to_cpu(dblock->bb_numrecs); |
1739 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); | 1698 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); |
@@ -1862,7 +1821,7 @@ xfs_bmbt_delete( | |||
1862 | * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. | 1821 | * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. |
1863 | */ | 1822 | */ |
1864 | 1823 | ||
1865 | STATIC __inline__ void | 1824 | STATIC_INLINE void |
1866 | __xfs_bmbt_get_all( | 1825 | __xfs_bmbt_get_all( |
1867 | __uint64_t l0, | 1826 | __uint64_t l0, |
1868 | __uint64_t l1, | 1827 | __uint64_t l1, |
@@ -2016,30 +1975,6 @@ xfs_bmbt_disk_get_blockcount( | |||
2016 | } | 1975 | } |
2017 | 1976 | ||
2018 | /* | 1977 | /* |
2019 | * Extract the startblock field from an on disk bmap extent record. | ||
2020 | */ | ||
2021 | xfs_fsblock_t | ||
2022 | xfs_bmbt_disk_get_startblock( | ||
2023 | xfs_bmbt_rec_t *r) | ||
2024 | { | ||
2025 | #if XFS_BIG_BLKNOS | ||
2026 | return (((xfs_fsblock_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) | | ||
2027 | (((xfs_fsblock_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21); | ||
2028 | #else | ||
2029 | #ifdef DEBUG | ||
2030 | xfs_dfsbno_t b; | ||
2031 | |||
2032 | b = (((xfs_dfsbno_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) | | ||
2033 | (((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21); | ||
2034 | ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); | ||
2035 | return (xfs_fsblock_t)b; | ||
2036 | #else /* !DEBUG */ | ||
2037 | return (xfs_fsblock_t)(((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21); | ||
2038 | #endif /* DEBUG */ | ||
2039 | #endif /* XFS_BIG_BLKNOS */ | ||
2040 | } | ||
2041 | |||
2042 | /* | ||
2043 | * Extract the startoff field from a disk format bmap extent record. | 1978 | * Extract the startoff field from a disk format bmap extent record. |
2044 | */ | 1979 | */ |
2045 | xfs_fileoff_t | 1980 | xfs_fileoff_t |
@@ -2049,17 +1984,6 @@ xfs_bmbt_disk_get_startoff( | |||
2049 | return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) & | 1984 | return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) & |
2050 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; | 1985 | XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; |
2051 | } | 1986 | } |
2052 | |||
2053 | xfs_exntst_t | ||
2054 | xfs_bmbt_disk_get_state( | ||
2055 | xfs_bmbt_rec_t *r) | ||
2056 | { | ||
2057 | int ext_flag; | ||
2058 | |||
2059 | ext_flag = (int)((INT_GET(r->l0, ARCH_CONVERT)) >> (64 - BMBT_EXNTFLAG_BITLEN)); | ||
2060 | return xfs_extent_state(xfs_bmbt_disk_get_blockcount(r), | ||
2061 | ext_flag); | ||
2062 | } | ||
2063 | #endif /* XFS_NATIVE_HOST */ | 1987 | #endif /* XFS_NATIVE_HOST */ |
2064 | 1988 | ||
2065 | 1989 | ||
@@ -2684,9 +2608,9 @@ xfs_bmbt_to_bmdr( | |||
2684 | dblock->bb_numrecs = rblock->bb_numrecs; | 2608 | dblock->bb_numrecs = rblock->bb_numrecs; |
2685 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); | 2609 | dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); |
2686 | fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); | 2610 | fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); |
2687 | tkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); | 2611 | tkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); |
2688 | fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); | 2612 | fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); |
2689 | tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); | 2613 | tpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); |
2690 | dmxr = be16_to_cpu(dblock->bb_numrecs); | 2614 | dmxr = be16_to_cpu(dblock->bb_numrecs); |
2691 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); | 2615 | memcpy(tkp, fkp, sizeof(*fkp) * dmxr); |
2692 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); | 2616 | memcpy(tpp, fpp, sizeof(*fpp) * dmxr); |
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h index 49539de9525b..a77b1b753d0c 100644 --- a/fs/xfs/xfs_bmap_btree.h +++ b/fs/xfs/xfs_bmap_btree.h | |||
@@ -175,19 +175,11 @@ typedef struct xfs_btree_lblock xfs_bmbt_block_t; | |||
175 | 175 | ||
176 | #define XFS_BUF_TO_BMBT_BLOCK(bp) ((xfs_bmbt_block_t *)XFS_BUF_PTR(bp)) | 176 | #define XFS_BUF_TO_BMBT_BLOCK(bp) ((xfs_bmbt_block_t *)XFS_BUF_PTR(bp)) |
177 | 177 | ||
178 | #define XFS_BMAP_IBLOCK_SIZE(lev,cur) (1 << (cur)->bc_blocklog) | ||
179 | #define XFS_BMAP_RBLOCK_DSIZE(lev,cur) ((cur)->bc_private.b.forksize) | 178 | #define XFS_BMAP_RBLOCK_DSIZE(lev,cur) ((cur)->bc_private.b.forksize) |
180 | #define XFS_BMAP_RBLOCK_ISIZE(lev,cur) \ | 179 | #define XFS_BMAP_RBLOCK_ISIZE(lev,cur) \ |
181 | ((int)XFS_IFORK_PTR((cur)->bc_private.b.ip, \ | 180 | ((int)XFS_IFORK_PTR((cur)->bc_private.b.ip, \ |
182 | (cur)->bc_private.b.whichfork)->if_broot_bytes) | 181 | (cur)->bc_private.b.whichfork)->if_broot_bytes) |
183 | 182 | ||
184 | #define XFS_BMAP_BLOCK_DSIZE(lev,cur) \ | ||
185 | (((lev) == (cur)->bc_nlevels - 1 ? \ | ||
186 | XFS_BMAP_RBLOCK_DSIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur))) | ||
187 | #define XFS_BMAP_BLOCK_ISIZE(lev,cur) \ | ||
188 | (((lev) == (cur)->bc_nlevels - 1 ? \ | ||
189 | XFS_BMAP_RBLOCK_ISIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur))) | ||
190 | |||
191 | #define XFS_BMAP_BLOCK_DMAXRECS(lev,cur) \ | 183 | #define XFS_BMAP_BLOCK_DMAXRECS(lev,cur) \ |
192 | (((lev) == (cur)->bc_nlevels - 1 ? \ | 184 | (((lev) == (cur)->bc_nlevels - 1 ? \ |
193 | XFS_BTREE_BLOCK_MAXRECS(XFS_BMAP_RBLOCK_DSIZE(lev,cur), \ | 185 | XFS_BTREE_BLOCK_MAXRECS(XFS_BMAP_RBLOCK_DSIZE(lev,cur), \ |
@@ -210,37 +202,21 @@ typedef struct xfs_btree_lblock xfs_bmbt_block_t; | |||
210 | xfs_bmbt, (lev) == 0) : \ | 202 | xfs_bmbt, (lev) == 0) : \ |
211 | ((cur)->bc_mp->m_bmap_dmnr[(lev) != 0]))) | 203 | ((cur)->bc_mp->m_bmap_dmnr[(lev) != 0]))) |
212 | 204 | ||
213 | #define XFS_BMAP_REC_DADDR(bb,i,cur) \ | 205 | #define XFS_BMAP_REC_DADDR(bb,i,cur) (XFS_BTREE_REC_ADDR(xfs_bmbt, bb, i)) |
214 | (XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_DSIZE( \ | 206 | |
215 | be16_to_cpu((bb)->bb_level), cur), \ | 207 | #define XFS_BMAP_REC_IADDR(bb,i,cur) (XFS_BTREE_REC_ADDR(xfs_bmbt, bb, i)) |
216 | xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \ | ||
217 | be16_to_cpu((bb)->bb_level), cur))) | ||
218 | #define XFS_BMAP_REC_IADDR(bb,i,cur) \ | ||
219 | (XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_ISIZE( \ | ||
220 | be16_to_cpu((bb)->bb_level), cur), \ | ||
221 | xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \ | ||
222 | be16_to_cpu((bb)->bb_level), cur))) | ||
223 | 208 | ||
224 | #define XFS_BMAP_KEY_DADDR(bb,i,cur) \ | 209 | #define XFS_BMAP_KEY_DADDR(bb,i,cur) \ |
225 | (XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_DSIZE( \ | 210 | (XFS_BTREE_KEY_ADDR(xfs_bmbt, bb, i)) |
226 | be16_to_cpu((bb)->bb_level), cur), \ | 211 | |
227 | xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \ | ||
228 | be16_to_cpu((bb)->bb_level), cur))) | ||
229 | #define XFS_BMAP_KEY_IADDR(bb,i,cur) \ | 212 | #define XFS_BMAP_KEY_IADDR(bb,i,cur) \ |
230 | (XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_ISIZE( \ | 213 | (XFS_BTREE_KEY_ADDR(xfs_bmbt, bb, i)) |
231 | be16_to_cpu((bb)->bb_level), cur), \ | ||
232 | xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \ | ||
233 | be16_to_cpu((bb)->bb_level), cur))) | ||
234 | 214 | ||
235 | #define XFS_BMAP_PTR_DADDR(bb,i,cur) \ | 215 | #define XFS_BMAP_PTR_DADDR(bb,i,cur) \ |
236 | (XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_DSIZE( \ | 216 | (XFS_BTREE_PTR_ADDR(xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \ |
237 | be16_to_cpu((bb)->bb_level), cur), \ | ||
238 | xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \ | ||
239 | be16_to_cpu((bb)->bb_level), cur))) | 217 | be16_to_cpu((bb)->bb_level), cur))) |
240 | #define XFS_BMAP_PTR_IADDR(bb,i,cur) \ | 218 | #define XFS_BMAP_PTR_IADDR(bb,i,cur) \ |
241 | (XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_ISIZE( \ | 219 | (XFS_BTREE_PTR_ADDR(xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \ |
242 | be16_to_cpu((bb)->bb_level), cur), \ | ||
243 | xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \ | ||
244 | be16_to_cpu((bb)->bb_level), cur))) | 220 | be16_to_cpu((bb)->bb_level), cur))) |
245 | 221 | ||
246 | /* | 222 | /* |
@@ -248,11 +224,11 @@ typedef struct xfs_btree_lblock xfs_bmbt_block_t; | |||
248 | * we don't have a cursor. | 224 | * we don't have a cursor. |
249 | */ | 225 | */ |
250 | #define XFS_BMAP_BROOT_REC_ADDR(bb,i,sz) \ | 226 | #define XFS_BMAP_BROOT_REC_ADDR(bb,i,sz) \ |
251 | (XFS_BTREE_REC_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz))) | 227 | (XFS_BTREE_REC_ADDR(xfs_bmbt,bb,i)) |
252 | #define XFS_BMAP_BROOT_KEY_ADDR(bb,i,sz) \ | 228 | #define XFS_BMAP_BROOT_KEY_ADDR(bb,i,sz) \ |
253 | (XFS_BTREE_KEY_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz))) | 229 | (XFS_BTREE_KEY_ADDR(xfs_bmbt,bb,i)) |
254 | #define XFS_BMAP_BROOT_PTR_ADDR(bb,i,sz) \ | 230 | #define XFS_BMAP_BROOT_PTR_ADDR(bb,i,sz) \ |
255 | (XFS_BTREE_PTR_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz))) | 231 | (XFS_BTREE_PTR_ADDR(xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz))) |
256 | 232 | ||
257 | #define XFS_BMAP_BROOT_NUMRECS(bb) be16_to_cpu((bb)->bb_numrecs) | 233 | #define XFS_BMAP_BROOT_NUMRECS(bb) be16_to_cpu((bb)->bb_numrecs) |
258 | #define XFS_BMAP_BROOT_MAXRECS(sz) XFS_BTREE_BLOCK_MAXRECS(sz,xfs_bmbt,0) | 234 | #define XFS_BMAP_BROOT_MAXRECS(sz) XFS_BTREE_BLOCK_MAXRECS(sz,xfs_bmbt,0) |
@@ -315,15 +291,11 @@ extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_t *r); | |||
315 | 291 | ||
316 | #ifndef XFS_NATIVE_HOST | 292 | #ifndef XFS_NATIVE_HOST |
317 | extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s); | 293 | extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s); |
318 | extern xfs_exntst_t xfs_bmbt_disk_get_state(xfs_bmbt_rec_t *r); | ||
319 | extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r); | 294 | extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r); |
320 | extern xfs_fsblock_t xfs_bmbt_disk_get_startblock(xfs_bmbt_rec_t *r); | ||
321 | extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r); | 295 | extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r); |
322 | #else | 296 | #else |
323 | #define xfs_bmbt_disk_get_all(r, s) xfs_bmbt_get_all(r, s) | 297 | #define xfs_bmbt_disk_get_all(r, s) xfs_bmbt_get_all(r, s) |
324 | #define xfs_bmbt_disk_get_state(r) xfs_bmbt_get_state(r) | ||
325 | #define xfs_bmbt_disk_get_blockcount(r) xfs_bmbt_get_blockcount(r) | 298 | #define xfs_bmbt_disk_get_blockcount(r) xfs_bmbt_get_blockcount(r) |
326 | #define xfs_bmbt_disk_get_startblock(r) xfs_bmbt_get_blockcount(r) | ||
327 | #define xfs_bmbt_disk_get_startoff(r) xfs_bmbt_get_startoff(r) | 299 | #define xfs_bmbt_disk_get_startoff(r) xfs_bmbt_get_startoff(r) |
328 | #endif /* XFS_NATIVE_HOST */ | 300 | #endif /* XFS_NATIVE_HOST */ |
329 | 301 | ||
@@ -364,15 +336,6 @@ extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int); | |||
364 | extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t, | 336 | extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t, |
365 | xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t); | 337 | xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t); |
366 | 338 | ||
367 | #ifdef DEBUG | ||
368 | /* | ||
369 | * Get the data from the pointed-to record. | ||
370 | */ | ||
371 | extern int xfs_bmbt_get_rec(struct xfs_btree_cur *, xfs_fileoff_t *, | ||
372 | xfs_fsblock_t *, xfs_filblks_t *, | ||
373 | xfs_exntst_t *, int *); | ||
374 | #endif | ||
375 | |||
376 | #endif /* __KERNEL__ */ | 339 | #endif /* __KERNEL__ */ |
377 | 340 | ||
378 | #endif /* __XFS_BMAP_BTREE_H__ */ | 341 | #endif /* __XFS_BMAP_BTREE_H__ */ |
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h index 892b06c54263..4e27d55a1e73 100644 --- a/fs/xfs/xfs_btree.h +++ b/fs/xfs/xfs_btree.h | |||
@@ -122,13 +122,13 @@ extern const __uint32_t xfs_magics[]; | |||
122 | * Given block size, type prefix, block pointer, and index of requested entry | 122 | * Given block size, type prefix, block pointer, and index of requested entry |
123 | * (first entry numbered 1). | 123 | * (first entry numbered 1). |
124 | */ | 124 | */ |
125 | #define XFS_BTREE_REC_ADDR(bsz,t,bb,i,mxr) \ | 125 | #define XFS_BTREE_REC_ADDR(t,bb,i) \ |
126 | ((t ## _rec_t *)((char *)(bb) + sizeof(t ## _block_t) + \ | 126 | ((t ## _rec_t *)((char *)(bb) + sizeof(t ## _block_t) + \ |
127 | ((i) - 1) * sizeof(t ## _rec_t))) | 127 | ((i) - 1) * sizeof(t ## _rec_t))) |
128 | #define XFS_BTREE_KEY_ADDR(bsz,t,bb,i,mxr) \ | 128 | #define XFS_BTREE_KEY_ADDR(t,bb,i) \ |
129 | ((t ## _key_t *)((char *)(bb) + sizeof(t ## _block_t) + \ | 129 | ((t ## _key_t *)((char *)(bb) + sizeof(t ## _block_t) + \ |
130 | ((i) - 1) * sizeof(t ## _key_t))) | 130 | ((i) - 1) * sizeof(t ## _key_t))) |
131 | #define XFS_BTREE_PTR_ADDR(bsz,t,bb,i,mxr) \ | 131 | #define XFS_BTREE_PTR_ADDR(t,bb,i,mxr) \ |
132 | ((t ## _ptr_t *)((char *)(bb) + sizeof(t ## _block_t) + \ | 132 | ((t ## _ptr_t *)((char *)(bb) + sizeof(t ## _block_t) + \ |
133 | (mxr) * sizeof(t ## _key_t) + ((i) - 1) * sizeof(t ## _ptr_t))) | 133 | (mxr) * sizeof(t ## _key_t) + ((i) - 1) * sizeof(t ## _ptr_t))) |
134 | 134 | ||
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 7a55c248ea70..6c1bddc04e31 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -660,7 +660,7 @@ xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn) | |||
660 | /* | 660 | /* |
661 | * This is the ops vector shared by all buf log items. | 661 | * This is the ops vector shared by all buf log items. |
662 | */ | 662 | */ |
663 | STATIC struct xfs_item_ops xfs_buf_item_ops = { | 663 | static struct xfs_item_ops xfs_buf_item_ops = { |
664 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_buf_item_size, | 664 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_buf_item_size, |
665 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 665 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) |
666 | xfs_buf_item_format, | 666 | xfs_buf_item_format, |
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index 07c708c2b529..d7e136143066 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h | |||
@@ -21,23 +21,7 @@ | |||
21 | /* | 21 | /* |
22 | * This is the structure used to lay out a buf log item in the | 22 | * This is the structure used to lay out a buf log item in the |
23 | * log. The data map describes which 128 byte chunks of the buffer | 23 | * log. The data map describes which 128 byte chunks of the buffer |
24 | * have been logged. This structure works only on buffers that | 24 | * have been logged. |
25 | * reside up to the first TB in the filesystem. These buffers are | ||
26 | * generated only by pre-6.2 systems and are known as XFS_LI_6_1_BUF. | ||
27 | */ | ||
28 | typedef struct xfs_buf_log_format_v1 { | ||
29 | unsigned short blf_type; /* buf log item type indicator */ | ||
30 | unsigned short blf_size; /* size of this item */ | ||
31 | __int32_t blf_blkno; /* starting blkno of this buf */ | ||
32 | ushort blf_flags; /* misc state */ | ||
33 | ushort blf_len; /* number of blocks in this buf */ | ||
34 | unsigned int blf_map_size; /* size of data bitmap in words */ | ||
35 | unsigned int blf_data_map[1];/* variable size bitmap of */ | ||
36 | /* regions of buffer in this item */ | ||
37 | } xfs_buf_log_format_v1_t; | ||
38 | |||
39 | /* | ||
40 | * This is a form of the above structure with a 64 bit blkno field. | ||
41 | * For 6.2 and beyond, this is XFS_LI_BUF. We use this to log everything. | 25 | * For 6.2 and beyond, this is XFS_LI_BUF. We use this to log everything. |
42 | */ | 26 | */ |
43 | typedef struct xfs_buf_log_format_t { | 27 | typedef struct xfs_buf_log_format_t { |
diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h deleted file mode 100644 index 7a0e482dd436..000000000000 --- a/fs/xfs/xfs_cap.h +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_CAP_H__ | ||
19 | #define __XFS_CAP_H__ | ||
20 | |||
21 | /* | ||
22 | * Capabilities | ||
23 | */ | ||
24 | typedef __uint64_t xfs_cap_value_t; | ||
25 | |||
26 | typedef struct xfs_cap_set { | ||
27 | xfs_cap_value_t cap_effective; /* use in capability checks */ | ||
28 | xfs_cap_value_t cap_permitted; /* combined with file attrs */ | ||
29 | xfs_cap_value_t cap_inheritable;/* pass through exec */ | ||
30 | } xfs_cap_set_t; | ||
31 | |||
32 | /* On-disk XFS extended attribute names */ | ||
33 | #define SGI_CAP_FILE "SGI_CAP_FILE" | ||
34 | #define SGI_CAP_FILE_SIZE (sizeof(SGI_CAP_FILE)-1) | ||
35 | #define SGI_CAP_LINUX "SGI_CAP_LINUX" | ||
36 | #define SGI_CAP_LINUX_SIZE (sizeof(SGI_CAP_LINUX)-1) | ||
37 | |||
38 | /* | ||
39 | * For Linux, we take the bitfields directly from capability.h | ||
40 | * and no longer attempt to keep this attribute ondisk compatible | ||
41 | * with IRIX. Since this attribute is only set on executables, | ||
42 | * it just doesn't make much sense to try. We do use a different | ||
43 | * named attribute though, to avoid confusion. | ||
44 | */ | ||
45 | |||
46 | #ifdef __KERNEL__ | ||
47 | |||
48 | #ifdef CONFIG_FS_POSIX_CAP | ||
49 | |||
50 | #include <linux/posix_cap_xattr.h> | ||
51 | |||
52 | struct bhv_vnode; | ||
53 | |||
54 | extern int xfs_cap_vhascap(struct bhv_vnode *); | ||
55 | extern int xfs_cap_vset(struct bhv_vnode *, void *, size_t); | ||
56 | extern int xfs_cap_vget(struct bhv_vnode *, void *, size_t); | ||
57 | extern int xfs_cap_vremove(struct bhv_vnode *); | ||
58 | |||
59 | #define _CAP_EXISTS xfs_cap_vhascap | ||
60 | |||
61 | #else | ||
62 | #define xfs_cap_vset(v,p,sz) (-EOPNOTSUPP) | ||
63 | #define xfs_cap_vget(v,p,sz) (-EOPNOTSUPP) | ||
64 | #define xfs_cap_vremove(v) (-EOPNOTSUPP) | ||
65 | #define _CAP_EXISTS (NULL) | ||
66 | #endif | ||
67 | |||
68 | #endif /* __KERNEL__ */ | ||
69 | |||
70 | #endif /* __XFS_CAP_H__ */ | ||
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index a68bc1f1a313..aea37df4aa62 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -1090,8 +1090,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) | |||
1090 | if (blk->magic == XFS_DA_NODE_MAGIC) { | 1090 | if (blk->magic == XFS_DA_NODE_MAGIC) { |
1091 | node = blk->bp->data; | 1091 | node = blk->bp->data; |
1092 | max = be16_to_cpu(node->hdr.count); | 1092 | max = be16_to_cpu(node->hdr.count); |
1093 | btreehashval = node->btree[max-1].hashval; | 1093 | blk->hashval = be32_to_cpu(node->btree[max-1].hashval); |
1094 | blk->hashval = be32_to_cpu(btreehashval); | ||
1095 | 1094 | ||
1096 | /* | 1095 | /* |
1097 | * Binary search. (note: small blocks will skip loop) | 1096 | * Binary search. (note: small blocks will skip loop) |
@@ -2166,21 +2165,6 @@ xfs_da_reada_buf( | |||
2166 | return rval; | 2165 | return rval; |
2167 | } | 2166 | } |
2168 | 2167 | ||
2169 | /* | ||
2170 | * Calculate the number of bits needed to hold i different values. | ||
2171 | */ | ||
2172 | uint | ||
2173 | xfs_da_log2_roundup(uint i) | ||
2174 | { | ||
2175 | uint rval; | ||
2176 | |||
2177 | for (rval = 0; rval < NBBY * sizeof(i); rval++) { | ||
2178 | if ((1 << rval) >= i) | ||
2179 | break; | ||
2180 | } | ||
2181 | return(rval); | ||
2182 | } | ||
2183 | |||
2184 | kmem_zone_t *xfs_da_state_zone; /* anchor for state struct zone */ | 2168 | kmem_zone_t *xfs_da_state_zone; /* anchor for state struct zone */ |
2185 | kmem_zone_t *xfs_dabuf_zone; /* dabuf zone */ | 2169 | kmem_zone_t *xfs_dabuf_zone; /* dabuf zone */ |
2186 | 2170 | ||
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index 4ab865ec8b82..44dabf02f2a3 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h | |||
@@ -249,7 +249,6 @@ int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, | |||
249 | xfs_dabuf_t *dead_buf); | 249 | xfs_dabuf_t *dead_buf); |
250 | 250 | ||
251 | uint xfs_da_hashname(const uchar_t *name_string, int name_length); | 251 | uint xfs_da_hashname(const uchar_t *name_string, int name_length); |
252 | uint xfs_da_log2_roundup(uint i); | ||
253 | xfs_da_state_t *xfs_da_state_alloc(void); | 252 | xfs_da_state_t *xfs_da_state_alloc(void); |
254 | void xfs_da_state_free(xfs_da_state_t *state); | 253 | void xfs_da_state_free(xfs_da_state_t *state); |
255 | 254 | ||
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 50d0faea371d..b847e6a7a3f0 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include "xfs_itable.h" | 41 | #include "xfs_itable.h" |
42 | #include "xfs_dfrag.h" | 42 | #include "xfs_dfrag.h" |
43 | #include "xfs_error.h" | 43 | #include "xfs_error.h" |
44 | #include "xfs_mac.h" | ||
45 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
46 | 45 | ||
47 | /* | 46 | /* |
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index b95681b03d81..b1af54464f00 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c | |||
@@ -132,32 +132,6 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp) | |||
132 | } | 132 | } |
133 | 133 | ||
134 | int | 134 | int |
135 | xfs_errortag_clear(int error_tag, xfs_mount_t *mp) | ||
136 | { | ||
137 | int i; | ||
138 | int64_t fsid; | ||
139 | |||
140 | memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t)); | ||
141 | |||
142 | for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { | ||
143 | if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) { | ||
144 | xfs_etest[i] = 0; | ||
145 | xfs_etest_fsid[i] = 0LL; | ||
146 | kmem_free(xfs_etest_fsname[i], | ||
147 | strlen(xfs_etest_fsname[i]) + 1); | ||
148 | xfs_etest_fsname[i] = NULL; | ||
149 | cmn_err(CE_WARN, "Cleared XFS error tag #%d", | ||
150 | error_tag); | ||
151 | return 0; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | cmn_err(CE_WARN, "XFS error tag %d not on", error_tag); | ||
156 | |||
157 | return 1; | ||
158 | } | ||
159 | |||
160 | int | ||
161 | xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud) | 135 | xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud) |
162 | { | 136 | { |
163 | int i; | 137 | int i; |
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 0893e16b7d83..5599ada456a1 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h | |||
@@ -144,7 +144,6 @@ extern void xfs_error_test_init(void); | |||
144 | #endif /* __ANSI_CPP__ */ | 144 | #endif /* __ANSI_CPP__ */ |
145 | 145 | ||
146 | extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); | 146 | extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); |
147 | extern int xfs_errortag_clear(int error_tag, xfs_mount_t *mp); | ||
148 | extern int xfs_errortag_clearall(xfs_mount_t *mp); | 147 | extern int xfs_errortag_clearall(xfs_mount_t *mp); |
149 | extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud); | 148 | extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud); |
150 | #else | 149 | #else |
@@ -180,6 +179,6 @@ extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...); | |||
180 | xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args) | 179 | xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args) |
181 | 180 | ||
182 | #define xfs_fs_mount_cmn_err(f, fmt, args...) \ | 181 | #define xfs_fs_mount_cmn_err(f, fmt, args...) \ |
183 | ((f & XFS_MFSI_QUIET)? cmn_err(CE_WARN, "XFS: " fmt, ## args) : (void)0) | 182 | ((f & XFS_MFSI_QUIET)? (void)0 : cmn_err(CE_WARN, "XFS: " fmt, ## args)) |
184 | 183 | ||
185 | #endif /* __XFS_ERROR_H__ */ | 184 | #endif /* __XFS_ERROR_H__ */ |
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index 6dba78199faf..3b14427ee123 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c | |||
@@ -227,7 +227,7 @@ xfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn) | |||
227 | /* | 227 | /* |
228 | * This is the ops vector shared by all efi log items. | 228 | * This is the ops vector shared by all efi log items. |
229 | */ | 229 | */ |
230 | STATIC struct xfs_item_ops xfs_efi_item_ops = { | 230 | static struct xfs_item_ops xfs_efi_item_ops = { |
231 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_efi_item_size, | 231 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_efi_item_size, |
232 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 232 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) |
233 | xfs_efi_item_format, | 233 | xfs_efi_item_format, |
@@ -525,7 +525,7 @@ xfs_efd_item_committing(xfs_efd_log_item_t *efip, xfs_lsn_t lsn) | |||
525 | /* | 525 | /* |
526 | * This is the ops vector shared by all efd log items. | 526 | * This is the ops vector shared by all efd log items. |
527 | */ | 527 | */ |
528 | STATIC struct xfs_item_ops xfs_efd_item_ops = { | 528 | static struct xfs_item_ops xfs_efd_item_ops = { |
529 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_efd_item_size, | 529 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_efd_item_size, |
530 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 530 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) |
531 | xfs_efd_item_format, | 531 | xfs_efd_item_format, |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index c064e72ada9e..32c37c1c47ab 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -250,8 +250,7 @@ xfs_growfs_data_private( | |||
250 | block->bb_numrecs = cpu_to_be16(1); | 250 | block->bb_numrecs = cpu_to_be16(1); |
251 | block->bb_leftsib = cpu_to_be32(NULLAGBLOCK); | 251 | block->bb_leftsib = cpu_to_be32(NULLAGBLOCK); |
252 | block->bb_rightsib = cpu_to_be32(NULLAGBLOCK); | 252 | block->bb_rightsib = cpu_to_be32(NULLAGBLOCK); |
253 | arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc, | 253 | arec = XFS_BTREE_REC_ADDR(xfs_alloc, block, 1); |
254 | block, 1, mp->m_alloc_mxr[0]); | ||
255 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); | 254 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); |
256 | arec->ar_blockcount = cpu_to_be32( | 255 | arec->ar_blockcount = cpu_to_be32( |
257 | agsize - be32_to_cpu(arec->ar_startblock)); | 256 | agsize - be32_to_cpu(arec->ar_startblock)); |
@@ -272,8 +271,7 @@ xfs_growfs_data_private( | |||
272 | block->bb_numrecs = cpu_to_be16(1); | 271 | block->bb_numrecs = cpu_to_be16(1); |
273 | block->bb_leftsib = cpu_to_be32(NULLAGBLOCK); | 272 | block->bb_leftsib = cpu_to_be32(NULLAGBLOCK); |
274 | block->bb_rightsib = cpu_to_be32(NULLAGBLOCK); | 273 | block->bb_rightsib = cpu_to_be32(NULLAGBLOCK); |
275 | arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc, | 274 | arec = XFS_BTREE_REC_ADDR(xfs_alloc, block, 1); |
276 | block, 1, mp->m_alloc_mxr[0]); | ||
277 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); | 275 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); |
278 | arec->ar_blockcount = cpu_to_be32( | 276 | arec->ar_blockcount = cpu_to_be32( |
279 | agsize - be32_to_cpu(arec->ar_startblock)); | 277 | agsize - be32_to_cpu(arec->ar_startblock)); |
@@ -460,7 +458,7 @@ xfs_fs_counts( | |||
460 | { | 458 | { |
461 | unsigned long s; | 459 | unsigned long s; |
462 | 460 | ||
463 | xfs_icsb_sync_counters_lazy(mp); | 461 | xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT); |
464 | s = XFS_SB_LOCK(mp); | 462 | s = XFS_SB_LOCK(mp); |
465 | cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | 463 | cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); |
466 | cnt->freertx = mp->m_sb.sb_frextents; | 464 | cnt->freertx = mp->m_sb.sb_frextents; |
@@ -491,7 +489,7 @@ xfs_reserve_blocks( | |||
491 | __uint64_t *inval, | 489 | __uint64_t *inval, |
492 | xfs_fsop_resblks_t *outval) | 490 | xfs_fsop_resblks_t *outval) |
493 | { | 491 | { |
494 | __int64_t lcounter, delta; | 492 | __int64_t lcounter, delta, fdblks_delta; |
495 | __uint64_t request; | 493 | __uint64_t request; |
496 | unsigned long s; | 494 | unsigned long s; |
497 | 495 | ||
@@ -504,17 +502,35 @@ xfs_reserve_blocks( | |||
504 | } | 502 | } |
505 | 503 | ||
506 | request = *inval; | 504 | request = *inval; |
505 | |||
506 | /* | ||
507 | * With per-cpu counters, this becomes an interesting | ||
508 | * problem. we needto work out if we are freeing or allocation | ||
509 | * blocks first, then we can do the modification as necessary. | ||
510 | * | ||
511 | * We do this under the XFS_SB_LOCK so that if we are near | ||
512 | * ENOSPC, we will hold out any changes while we work out | ||
513 | * what to do. This means that the amount of free space can | ||
514 | * change while we do this, so we need to retry if we end up | ||
515 | * trying to reserve more space than is available. | ||
516 | * | ||
517 | * We also use the xfs_mod_incore_sb() interface so that we | ||
518 | * don't have to care about whether per cpu counter are | ||
519 | * enabled, disabled or even compiled in.... | ||
520 | */ | ||
521 | retry: | ||
507 | s = XFS_SB_LOCK(mp); | 522 | s = XFS_SB_LOCK(mp); |
523 | xfs_icsb_sync_counters_flags(mp, XFS_ICSB_SB_LOCKED); | ||
508 | 524 | ||
509 | /* | 525 | /* |
510 | * If our previous reservation was larger than the current value, | 526 | * If our previous reservation was larger than the current value, |
511 | * then move any unused blocks back to the free pool. | 527 | * then move any unused blocks back to the free pool. |
512 | */ | 528 | */ |
513 | 529 | fdblks_delta = 0; | |
514 | if (mp->m_resblks > request) { | 530 | if (mp->m_resblks > request) { |
515 | lcounter = mp->m_resblks_avail - request; | 531 | lcounter = mp->m_resblks_avail - request; |
516 | if (lcounter > 0) { /* release unused blocks */ | 532 | if (lcounter > 0) { /* release unused blocks */ |
517 | mp->m_sb.sb_fdblocks += lcounter; | 533 | fdblks_delta = lcounter; |
518 | mp->m_resblks_avail -= lcounter; | 534 | mp->m_resblks_avail -= lcounter; |
519 | } | 535 | } |
520 | mp->m_resblks = request; | 536 | mp->m_resblks = request; |
@@ -522,24 +538,50 @@ xfs_reserve_blocks( | |||
522 | __int64_t free; | 538 | __int64_t free; |
523 | 539 | ||
524 | free = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | 540 | free = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); |
541 | if (!free) | ||
542 | goto out; /* ENOSPC and fdblks_delta = 0 */ | ||
543 | |||
525 | delta = request - mp->m_resblks; | 544 | delta = request - mp->m_resblks; |
526 | lcounter = free - delta; | 545 | lcounter = free - delta; |
527 | if (lcounter < 0) { | 546 | if (lcounter < 0) { |
528 | /* We can't satisfy the request, just get what we can */ | 547 | /* We can't satisfy the request, just get what we can */ |
529 | mp->m_resblks += free; | 548 | mp->m_resblks += free; |
530 | mp->m_resblks_avail += free; | 549 | mp->m_resblks_avail += free; |
550 | fdblks_delta = -free; | ||
531 | mp->m_sb.sb_fdblocks = XFS_ALLOC_SET_ASIDE(mp); | 551 | mp->m_sb.sb_fdblocks = XFS_ALLOC_SET_ASIDE(mp); |
532 | } else { | 552 | } else { |
553 | fdblks_delta = -delta; | ||
533 | mp->m_sb.sb_fdblocks = | 554 | mp->m_sb.sb_fdblocks = |
534 | lcounter + XFS_ALLOC_SET_ASIDE(mp); | 555 | lcounter + XFS_ALLOC_SET_ASIDE(mp); |
535 | mp->m_resblks = request; | 556 | mp->m_resblks = request; |
536 | mp->m_resblks_avail += delta; | 557 | mp->m_resblks_avail += delta; |
537 | } | 558 | } |
538 | } | 559 | } |
539 | 560 | out: | |
540 | outval->resblks = mp->m_resblks; | 561 | outval->resblks = mp->m_resblks; |
541 | outval->resblks_avail = mp->m_resblks_avail; | 562 | outval->resblks_avail = mp->m_resblks_avail; |
542 | XFS_SB_UNLOCK(mp, s); | 563 | XFS_SB_UNLOCK(mp, s); |
564 | |||
565 | if (fdblks_delta) { | ||
566 | /* | ||
567 | * If we are putting blocks back here, m_resblks_avail is | ||
568 | * already at it's max so this will put it in the free pool. | ||
569 | * | ||
570 | * If we need space, we'll either succeed in getting it | ||
571 | * from the free block count or we'll get an enospc. If | ||
572 | * we get a ENOSPC, it means things changed while we were | ||
573 | * calculating fdblks_delta and so we should try again to | ||
574 | * see if there is anything left to reserve. | ||
575 | * | ||
576 | * Don't set the reserved flag here - we don't want to reserve | ||
577 | * the extra reserve blocks from the reserve..... | ||
578 | */ | ||
579 | int error; | ||
580 | error = xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, fdblks_delta, 0); | ||
581 | if (error == ENOSPC) | ||
582 | goto retry; | ||
583 | } | ||
584 | |||
543 | return 0; | 585 | return 0; |
544 | } | 586 | } |
545 | 587 | ||
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index a446e5a115c6..b5feb3e77116 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -342,7 +342,7 @@ xfs_ialloc_ag_alloc( | |||
342 | return 0; | 342 | return 0; |
343 | } | 343 | } |
344 | 344 | ||
345 | STATIC __inline xfs_agnumber_t | 345 | STATIC_INLINE xfs_agnumber_t |
346 | xfs_ialloc_next_ag( | 346 | xfs_ialloc_next_ag( |
347 | xfs_mount_t *mp) | 347 | xfs_mount_t *mp) |
348 | { | 348 | { |
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h index 2c0e49893ff7..bf8e9aff272e 100644 --- a/fs/xfs/xfs_ialloc_btree.h +++ b/fs/xfs/xfs_ialloc_btree.h | |||
@@ -89,7 +89,6 @@ typedef struct xfs_btree_sblock xfs_inobt_block_t; | |||
89 | /* | 89 | /* |
90 | * Real block structures have a size equal to the disk block size. | 90 | * Real block structures have a size equal to the disk block size. |
91 | */ | 91 | */ |
92 | #define XFS_INOBT_BLOCK_SIZE(lev,cur) (1 << (cur)->bc_blocklog) | ||
93 | #define XFS_INOBT_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_inobt_mxr[lev != 0]) | 92 | #define XFS_INOBT_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_inobt_mxr[lev != 0]) |
94 | #define XFS_INOBT_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_inobt_mnr[lev != 0]) | 93 | #define XFS_INOBT_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_inobt_mnr[lev != 0]) |
95 | #define XFS_INOBT_IS_LAST_REC(cur) \ | 94 | #define XFS_INOBT_IS_LAST_REC(cur) \ |
@@ -110,14 +109,13 @@ typedef struct xfs_btree_sblock xfs_inobt_block_t; | |||
110 | * Record, key, and pointer address macros for btree blocks. | 109 | * Record, key, and pointer address macros for btree blocks. |
111 | */ | 110 | */ |
112 | #define XFS_INOBT_REC_ADDR(bb,i,cur) \ | 111 | #define XFS_INOBT_REC_ADDR(bb,i,cur) \ |
113 | (XFS_BTREE_REC_ADDR(XFS_INOBT_BLOCK_SIZE(0,cur), xfs_inobt, bb, \ | 112 | (XFS_BTREE_REC_ADDR(xfs_inobt, bb, i)) |
114 | i, XFS_INOBT_BLOCK_MAXRECS(0, cur))) | 113 | |
115 | #define XFS_INOBT_KEY_ADDR(bb,i,cur) \ | 114 | #define XFS_INOBT_KEY_ADDR(bb,i,cur) \ |
116 | (XFS_BTREE_KEY_ADDR(XFS_INOBT_BLOCK_SIZE(1,cur), xfs_inobt, bb, \ | 115 | (XFS_BTREE_KEY_ADDR(xfs_inobt, bb, i)) |
117 | i, XFS_INOBT_BLOCK_MAXRECS(1, cur))) | ||
118 | 116 | ||
119 | #define XFS_INOBT_PTR_ADDR(bb,i,cur) \ | 117 | #define XFS_INOBT_PTR_ADDR(bb,i,cur) \ |
120 | (XFS_BTREE_PTR_ADDR(XFS_INOBT_BLOCK_SIZE(1,cur), xfs_inobt, bb, \ | 118 | (XFS_BTREE_PTR_ADDR(xfs_inobt, bb, \ |
121 | i, XFS_INOBT_BLOCK_MAXRECS(1, cur))) | 119 | i, XFS_INOBT_BLOCK_MAXRECS(1, cur))) |
122 | 120 | ||
123 | /* | 121 | /* |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 44dfac521285..3da9829c19d5 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include "xfs_utils.h" | 47 | #include "xfs_utils.h" |
48 | #include "xfs_dir2_trace.h" | 48 | #include "xfs_dir2_trace.h" |
49 | #include "xfs_quota.h" | 49 | #include "xfs_quota.h" |
50 | #include "xfs_mac.h" | ||
51 | #include "xfs_acl.h" | 50 | #include "xfs_acl.h" |
52 | 51 | ||
53 | 52 | ||
@@ -1699,8 +1698,7 @@ xfs_itruncate_finish( | |||
1699 | * Duplicate the transaction that has the permanent | 1698 | * Duplicate the transaction that has the permanent |
1700 | * reservation and commit the old transaction. | 1699 | * reservation and commit the old transaction. |
1701 | */ | 1700 | */ |
1702 | error = xfs_bmap_finish(tp, &free_list, first_block, | 1701 | error = xfs_bmap_finish(tp, &free_list, &committed); |
1703 | &committed); | ||
1704 | ntp = *tp; | 1702 | ntp = *tp; |
1705 | if (error) { | 1703 | if (error) { |
1706 | /* | 1704 | /* |
@@ -1810,7 +1808,7 @@ xfs_igrow_start( | |||
1810 | * and any blocks between the old and new file sizes. | 1808 | * and any blocks between the old and new file sizes. |
1811 | */ | 1809 | */ |
1812 | error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size, | 1810 | error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size, |
1813 | ip->i_d.di_size, new_size); | 1811 | ip->i_d.di_size); |
1814 | return error; | 1812 | return error; |
1815 | } | 1813 | } |
1816 | 1814 | ||
@@ -2125,7 +2123,7 @@ xfs_iunlink_remove( | |||
2125 | return 0; | 2123 | return 0; |
2126 | } | 2124 | } |
2127 | 2125 | ||
2128 | static __inline__ int xfs_inode_clean(xfs_inode_t *ip) | 2126 | STATIC_INLINE int xfs_inode_clean(xfs_inode_t *ip) |
2129 | { | 2127 | { |
2130 | return (((ip->i_itemp == NULL) || | 2128 | return (((ip->i_itemp == NULL) || |
2131 | !(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)) && | 2129 | !(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)) && |
@@ -2707,10 +2705,24 @@ xfs_idestroy( | |||
2707 | ktrace_free(ip->i_dir_trace); | 2705 | ktrace_free(ip->i_dir_trace); |
2708 | #endif | 2706 | #endif |
2709 | if (ip->i_itemp) { | 2707 | if (ip->i_itemp) { |
2710 | /* XXXdpd should be able to assert this but shutdown | 2708 | /* |
2711 | * is leaving the AIL behind. */ | 2709 | * Only if we are shutting down the fs will we see an |
2712 | ASSERT(((ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL) == 0) || | 2710 | * inode still in the AIL. If it is there, we should remove |
2713 | XFS_FORCED_SHUTDOWN(ip->i_mount)); | 2711 | * it to prevent a use-after-free from occurring. |
2712 | */ | ||
2713 | xfs_mount_t *mp = ip->i_mount; | ||
2714 | xfs_log_item_t *lip = &ip->i_itemp->ili_item; | ||
2715 | int s; | ||
2716 | |||
2717 | ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) || | ||
2718 | XFS_FORCED_SHUTDOWN(ip->i_mount)); | ||
2719 | if (lip->li_flags & XFS_LI_IN_AIL) { | ||
2720 | AIL_LOCK(mp, s); | ||
2721 | if (lip->li_flags & XFS_LI_IN_AIL) | ||
2722 | xfs_trans_delete_ail(mp, lip, s); | ||
2723 | else | ||
2724 | AIL_UNLOCK(mp, s); | ||
2725 | } | ||
2714 | xfs_inode_item_destroy(ip); | 2726 | xfs_inode_item_destroy(ip); |
2715 | } | 2727 | } |
2716 | kmem_zone_free(xfs_inode_zone, ip); | 2728 | kmem_zone_free(xfs_inode_zone, ip); |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index a7a92251eb56..565d470a6b4a 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -887,7 +887,7 @@ xfs_inode_item_committing( | |||
887 | /* | 887 | /* |
888 | * This is the ops vector shared by all buf log items. | 888 | * This is the ops vector shared by all buf log items. |
889 | */ | 889 | */ |
890 | STATIC struct xfs_item_ops xfs_inode_item_ops = { | 890 | static struct xfs_item_ops xfs_inode_item_ops = { |
891 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_inode_item_size, | 891 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_inode_item_size, |
892 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 892 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) |
893 | xfs_inode_item_format, | 893 | xfs_inode_item_format, |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 19655124da78..cc6a7b5a9912 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "xfs_itable.h" | 43 | #include "xfs_itable.h" |
44 | #include "xfs_rw.h" | 44 | #include "xfs_rw.h" |
45 | #include "xfs_acl.h" | 45 | #include "xfs_acl.h" |
46 | #include "xfs_cap.h" | ||
47 | #include "xfs_mac.h" | ||
48 | #include "xfs_attr.h" | 46 | #include "xfs_attr.h" |
49 | #include "xfs_buf_item.h" | 47 | #include "xfs_buf_item.h" |
50 | #include "xfs_trans_space.h" | 48 | #include "xfs_trans_space.h" |
@@ -542,7 +540,7 @@ xfs_iomap_write_direct( | |||
542 | /* | 540 | /* |
543 | * Complete the transaction | 541 | * Complete the transaction |
544 | */ | 542 | */ |
545 | error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); | 543 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
546 | if (error) | 544 | if (error) |
547 | goto error0; | 545 | goto error0; |
548 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); | 546 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); |
@@ -838,8 +836,7 @@ xfs_iomap_write_allocate( | |||
838 | if (error) | 836 | if (error) |
839 | goto trans_cancel; | 837 | goto trans_cancel; |
840 | 838 | ||
841 | error = xfs_bmap_finish(&tp, &free_list, | 839 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
842 | first_block, &committed); | ||
843 | if (error) | 840 | if (error) |
844 | goto trans_cancel; | 841 | goto trans_cancel; |
845 | 842 | ||
@@ -947,8 +944,7 @@ xfs_iomap_write_unwritten( | |||
947 | if (error) | 944 | if (error) |
948 | goto error_on_bmapi_transaction; | 945 | goto error_on_bmapi_transaction; |
949 | 946 | ||
950 | error = xfs_bmap_finish(&(tp), &(free_list), | 947 | error = xfs_bmap_finish(&(tp), &(free_list), &committed); |
951 | firstfsb, &committed); | ||
952 | if (error) | 948 | if (error) |
953 | goto error_on_bmapi_transaction; | 949 | goto error_on_bmapi_transaction; |
954 | 950 | ||
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 3cb678e3a132..ca74d3f5910e 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -1514,7 +1514,6 @@ xlog_recover_reorder_trans( | |||
1514 | { | 1514 | { |
1515 | xlog_recover_item_t *first_item, *itemq, *itemq_next; | 1515 | xlog_recover_item_t *first_item, *itemq, *itemq_next; |
1516 | xfs_buf_log_format_t *buf_f; | 1516 | xfs_buf_log_format_t *buf_f; |
1517 | xfs_buf_log_format_v1_t *obuf_f; | ||
1518 | ushort flags = 0; | 1517 | ushort flags = 0; |
1519 | 1518 | ||
1520 | first_item = itemq = trans->r_itemq; | 1519 | first_item = itemq = trans->r_itemq; |
@@ -1522,29 +1521,16 @@ xlog_recover_reorder_trans( | |||
1522 | do { | 1521 | do { |
1523 | itemq_next = itemq->ri_next; | 1522 | itemq_next = itemq->ri_next; |
1524 | buf_f = (xfs_buf_log_format_t *)itemq->ri_buf[0].i_addr; | 1523 | buf_f = (xfs_buf_log_format_t *)itemq->ri_buf[0].i_addr; |
1525 | switch (ITEM_TYPE(itemq)) { | ||
1526 | case XFS_LI_BUF: | ||
1527 | flags = buf_f->blf_flags; | ||
1528 | break; | ||
1529 | case XFS_LI_6_1_BUF: | ||
1530 | case XFS_LI_5_3_BUF: | ||
1531 | obuf_f = (xfs_buf_log_format_v1_t*)buf_f; | ||
1532 | flags = obuf_f->blf_flags; | ||
1533 | break; | ||
1534 | } | ||
1535 | 1524 | ||
1536 | switch (ITEM_TYPE(itemq)) { | 1525 | switch (ITEM_TYPE(itemq)) { |
1537 | case XFS_LI_BUF: | 1526 | case XFS_LI_BUF: |
1538 | case XFS_LI_6_1_BUF: | 1527 | flags = buf_f->blf_flags; |
1539 | case XFS_LI_5_3_BUF: | ||
1540 | if (!(flags & XFS_BLI_CANCEL)) { | 1528 | if (!(flags & XFS_BLI_CANCEL)) { |
1541 | xlog_recover_insert_item_frontq(&trans->r_itemq, | 1529 | xlog_recover_insert_item_frontq(&trans->r_itemq, |
1542 | itemq); | 1530 | itemq); |
1543 | break; | 1531 | break; |
1544 | } | 1532 | } |
1545 | case XFS_LI_INODE: | 1533 | case XFS_LI_INODE: |
1546 | case XFS_LI_6_1_INODE: | ||
1547 | case XFS_LI_5_3_INODE: | ||
1548 | case XFS_LI_DQUOT: | 1534 | case XFS_LI_DQUOT: |
1549 | case XFS_LI_QUOTAOFF: | 1535 | case XFS_LI_QUOTAOFF: |
1550 | case XFS_LI_EFD: | 1536 | case XFS_LI_EFD: |
@@ -1583,7 +1569,6 @@ xlog_recover_do_buffer_pass1( | |||
1583 | xfs_buf_cancel_t *nextp; | 1569 | xfs_buf_cancel_t *nextp; |
1584 | xfs_buf_cancel_t *prevp; | 1570 | xfs_buf_cancel_t *prevp; |
1585 | xfs_buf_cancel_t **bucket; | 1571 | xfs_buf_cancel_t **bucket; |
1586 | xfs_buf_log_format_v1_t *obuf_f; | ||
1587 | xfs_daddr_t blkno = 0; | 1572 | xfs_daddr_t blkno = 0; |
1588 | uint len = 0; | 1573 | uint len = 0; |
1589 | ushort flags = 0; | 1574 | ushort flags = 0; |
@@ -1594,13 +1579,6 @@ xlog_recover_do_buffer_pass1( | |||
1594 | len = buf_f->blf_len; | 1579 | len = buf_f->blf_len; |
1595 | flags = buf_f->blf_flags; | 1580 | flags = buf_f->blf_flags; |
1596 | break; | 1581 | break; |
1597 | case XFS_LI_6_1_BUF: | ||
1598 | case XFS_LI_5_3_BUF: | ||
1599 | obuf_f = (xfs_buf_log_format_v1_t*)buf_f; | ||
1600 | blkno = (xfs_daddr_t) obuf_f->blf_blkno; | ||
1601 | len = obuf_f->blf_len; | ||
1602 | flags = obuf_f->blf_flags; | ||
1603 | break; | ||
1604 | } | 1582 | } |
1605 | 1583 | ||
1606 | /* | 1584 | /* |
@@ -1746,7 +1724,6 @@ xlog_recover_do_buffer_pass2( | |||
1746 | xlog_t *log, | 1724 | xlog_t *log, |
1747 | xfs_buf_log_format_t *buf_f) | 1725 | xfs_buf_log_format_t *buf_f) |
1748 | { | 1726 | { |
1749 | xfs_buf_log_format_v1_t *obuf_f; | ||
1750 | xfs_daddr_t blkno = 0; | 1727 | xfs_daddr_t blkno = 0; |
1751 | ushort flags = 0; | 1728 | ushort flags = 0; |
1752 | uint len = 0; | 1729 | uint len = 0; |
@@ -1757,13 +1734,6 @@ xlog_recover_do_buffer_pass2( | |||
1757 | flags = buf_f->blf_flags; | 1734 | flags = buf_f->blf_flags; |
1758 | len = buf_f->blf_len; | 1735 | len = buf_f->blf_len; |
1759 | break; | 1736 | break; |
1760 | case XFS_LI_6_1_BUF: | ||
1761 | case XFS_LI_5_3_BUF: | ||
1762 | obuf_f = (xfs_buf_log_format_v1_t*)buf_f; | ||
1763 | blkno = (xfs_daddr_t) obuf_f->blf_blkno; | ||
1764 | flags = obuf_f->blf_flags; | ||
1765 | len = (xfs_daddr_t) obuf_f->blf_len; | ||
1766 | break; | ||
1767 | } | 1737 | } |
1768 | 1738 | ||
1769 | return xlog_check_buffer_cancelled(log, blkno, len, flags); | 1739 | return xlog_check_buffer_cancelled(log, blkno, len, flags); |
@@ -1799,7 +1769,6 @@ xlog_recover_do_inode_buffer( | |||
1799 | int inodes_per_buf; | 1769 | int inodes_per_buf; |
1800 | xfs_agino_t *logged_nextp; | 1770 | xfs_agino_t *logged_nextp; |
1801 | xfs_agino_t *buffer_nextp; | 1771 | xfs_agino_t *buffer_nextp; |
1802 | xfs_buf_log_format_v1_t *obuf_f; | ||
1803 | unsigned int *data_map = NULL; | 1772 | unsigned int *data_map = NULL; |
1804 | unsigned int map_size = 0; | 1773 | unsigned int map_size = 0; |
1805 | 1774 | ||
@@ -1808,12 +1777,6 @@ xlog_recover_do_inode_buffer( | |||
1808 | data_map = buf_f->blf_data_map; | 1777 | data_map = buf_f->blf_data_map; |
1809 | map_size = buf_f->blf_map_size; | 1778 | map_size = buf_f->blf_map_size; |
1810 | break; | 1779 | break; |
1811 | case XFS_LI_6_1_BUF: | ||
1812 | case XFS_LI_5_3_BUF: | ||
1813 | obuf_f = (xfs_buf_log_format_v1_t*)buf_f; | ||
1814 | data_map = obuf_f->blf_data_map; | ||
1815 | map_size = obuf_f->blf_map_size; | ||
1816 | break; | ||
1817 | } | 1780 | } |
1818 | /* | 1781 | /* |
1819 | * Set the variables corresponding to the current region to | 1782 | * Set the variables corresponding to the current region to |
@@ -1912,7 +1875,6 @@ xlog_recover_do_reg_buffer( | |||
1912 | int i; | 1875 | int i; |
1913 | int bit; | 1876 | int bit; |
1914 | int nbits; | 1877 | int nbits; |
1915 | xfs_buf_log_format_v1_t *obuf_f; | ||
1916 | unsigned int *data_map = NULL; | 1878 | unsigned int *data_map = NULL; |
1917 | unsigned int map_size = 0; | 1879 | unsigned int map_size = 0; |
1918 | int error; | 1880 | int error; |
@@ -1922,12 +1884,6 @@ xlog_recover_do_reg_buffer( | |||
1922 | data_map = buf_f->blf_data_map; | 1884 | data_map = buf_f->blf_data_map; |
1923 | map_size = buf_f->blf_map_size; | 1885 | map_size = buf_f->blf_map_size; |
1924 | break; | 1886 | break; |
1925 | case XFS_LI_6_1_BUF: | ||
1926 | case XFS_LI_5_3_BUF: | ||
1927 | obuf_f = (xfs_buf_log_format_v1_t*)buf_f; | ||
1928 | data_map = obuf_f->blf_data_map; | ||
1929 | map_size = obuf_f->blf_map_size; | ||
1930 | break; | ||
1931 | } | 1887 | } |
1932 | bit = 0; | 1888 | bit = 0; |
1933 | i = 1; /* 0 is the buf format structure */ | 1889 | i = 1; /* 0 is the buf format structure */ |
@@ -2160,7 +2116,6 @@ xlog_recover_do_buffer_trans( | |||
2160 | int pass) | 2116 | int pass) |
2161 | { | 2117 | { |
2162 | xfs_buf_log_format_t *buf_f; | 2118 | xfs_buf_log_format_t *buf_f; |
2163 | xfs_buf_log_format_v1_t *obuf_f; | ||
2164 | xfs_mount_t *mp; | 2119 | xfs_mount_t *mp; |
2165 | xfs_buf_t *bp; | 2120 | xfs_buf_t *bp; |
2166 | int error; | 2121 | int error; |
@@ -2197,13 +2152,6 @@ xlog_recover_do_buffer_trans( | |||
2197 | len = buf_f->blf_len; | 2152 | len = buf_f->blf_len; |
2198 | flags = buf_f->blf_flags; | 2153 | flags = buf_f->blf_flags; |
2199 | break; | 2154 | break; |
2200 | case XFS_LI_6_1_BUF: | ||
2201 | case XFS_LI_5_3_BUF: | ||
2202 | obuf_f = (xfs_buf_log_format_v1_t*)buf_f; | ||
2203 | blkno = obuf_f->blf_blkno; | ||
2204 | len = obuf_f->blf_len; | ||
2205 | flags = obuf_f->blf_flags; | ||
2206 | break; | ||
2207 | default: | 2155 | default: |
2208 | xfs_fs_cmn_err(CE_ALERT, log->l_mp, | 2156 | xfs_fs_cmn_err(CE_ALERT, log->l_mp, |
2209 | "xfs_log_recover: unknown buffer type 0x%x, logdev %s", | 2157 | "xfs_log_recover: unknown buffer type 0x%x, logdev %s", |
@@ -2830,9 +2778,7 @@ xlog_recover_do_trans( | |||
2830 | * where xfs_daddr_t is 32-bits but mount will warn us | 2778 | * where xfs_daddr_t is 32-bits but mount will warn us |
2831 | * off a > 1 TB filesystem before we get here. | 2779 | * off a > 1 TB filesystem before we get here. |
2832 | */ | 2780 | */ |
2833 | if ((ITEM_TYPE(item) == XFS_LI_BUF) || | 2781 | if ((ITEM_TYPE(item) == XFS_LI_BUF)) { |
2834 | (ITEM_TYPE(item) == XFS_LI_6_1_BUF) || | ||
2835 | (ITEM_TYPE(item) == XFS_LI_5_3_BUF)) { | ||
2836 | if ((error = xlog_recover_do_buffer_trans(log, item, | 2782 | if ((error = xlog_recover_do_buffer_trans(log, item, |
2837 | pass))) | 2783 | pass))) |
2838 | break; | 2784 | break; |
@@ -3902,6 +3848,9 @@ xlog_do_recover( | |||
3902 | ASSERT(XFS_SB_GOOD_VERSION(sbp)); | 3848 | ASSERT(XFS_SB_GOOD_VERSION(sbp)); |
3903 | xfs_buf_relse(bp); | 3849 | xfs_buf_relse(bp); |
3904 | 3850 | ||
3851 | /* We've re-read the superblock so re-initialize per-cpu counters */ | ||
3852 | xfs_icsb_reinit_counters(log->l_mp); | ||
3853 | |||
3905 | xlog_recover_check_summary(log); | 3854 | xlog_recover_check_summary(log); |
3906 | 3855 | ||
3907 | /* Normal transactions can now occur */ | 3856 | /* Normal transactions can now occur */ |
diff --git a/fs/xfs/xfs_mac.h b/fs/xfs/xfs_mac.h deleted file mode 100644 index 18e0e98e03d0..000000000000 --- a/fs/xfs/xfs_mac.h +++ /dev/null | |||
@@ -1,106 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_MAC_H__ | ||
19 | #define __XFS_MAC_H__ | ||
20 | |||
21 | /* | ||
22 | * Mandatory Access Control | ||
23 | * | ||
24 | * Layout of a composite MAC label: | ||
25 | * ml_list contains the list of categories (MSEN) followed by the list of | ||
26 | * divisions (MINT). This is actually a header for the data structure which | ||
27 | * will have an ml_list with more than one element. | ||
28 | * | ||
29 | * ------------------------------- | ||
30 | * | ml_msen_type | ml_mint_type | | ||
31 | * ------------------------------- | ||
32 | * | ml_level | ml_grade | | ||
33 | * ------------------------------- | ||
34 | * | ml_catcount | | ||
35 | * ------------------------------- | ||
36 | * | ml_divcount | | ||
37 | * ------------------------------- | ||
38 | * | category 1 | | ||
39 | * | . . . | | ||
40 | * | category N | (where N = ml_catcount) | ||
41 | * ------------------------------- | ||
42 | * | division 1 | | ||
43 | * | . . . | | ||
44 | * | division M | (where M = ml_divcount) | ||
45 | * ------------------------------- | ||
46 | */ | ||
47 | #define XFS_MAC_MAX_SETS 250 | ||
48 | typedef struct xfs_mac_label { | ||
49 | __uint8_t ml_msen_type; /* MSEN label type */ | ||
50 | __uint8_t ml_mint_type; /* MINT label type */ | ||
51 | __uint8_t ml_level; /* Hierarchical level */ | ||
52 | __uint8_t ml_grade; /* Hierarchical grade */ | ||
53 | __uint16_t ml_catcount; /* Category count */ | ||
54 | __uint16_t ml_divcount; /* Division count */ | ||
55 | /* Category set, then Division set */ | ||
56 | __uint16_t ml_list[XFS_MAC_MAX_SETS]; | ||
57 | } xfs_mac_label_t; | ||
58 | |||
59 | /* MSEN label type names. Choose an upper case ASCII character. */ | ||
60 | #define XFS_MSEN_ADMIN_LABEL 'A' /* Admin: low<admin != tcsec<high */ | ||
61 | #define XFS_MSEN_EQUAL_LABEL 'E' /* Wildcard - always equal */ | ||
62 | #define XFS_MSEN_HIGH_LABEL 'H' /* System High - always dominates */ | ||
63 | #define XFS_MSEN_MLD_HIGH_LABEL 'I' /* System High, multi-level dir */ | ||
64 | #define XFS_MSEN_LOW_LABEL 'L' /* System Low - always dominated */ | ||
65 | #define XFS_MSEN_MLD_LABEL 'M' /* TCSEC label on a multi-level dir */ | ||
66 | #define XFS_MSEN_MLD_LOW_LABEL 'N' /* System Low, multi-level dir */ | ||
67 | #define XFS_MSEN_TCSEC_LABEL 'T' /* TCSEC label */ | ||
68 | #define XFS_MSEN_UNKNOWN_LABEL 'U' /* unknown label */ | ||
69 | |||
70 | /* MINT label type names. Choose a lower case ASCII character. */ | ||
71 | #define XFS_MINT_BIBA_LABEL 'b' /* Dual of a TCSEC label */ | ||
72 | #define XFS_MINT_EQUAL_LABEL 'e' /* Wildcard - always equal */ | ||
73 | #define XFS_MINT_HIGH_LABEL 'h' /* High Grade - always dominates */ | ||
74 | #define XFS_MINT_LOW_LABEL 'l' /* Low Grade - always dominated */ | ||
75 | |||
76 | /* On-disk XFS extended attribute names */ | ||
77 | #define SGI_MAC_FILE "SGI_MAC_FILE" | ||
78 | #define SGI_MAC_FILE_SIZE (sizeof(SGI_MAC_FILE)-1) | ||
79 | |||
80 | |||
81 | #ifdef __KERNEL__ | ||
82 | |||
83 | #ifdef CONFIG_FS_POSIX_MAC | ||
84 | |||
85 | /* NOT YET IMPLEMENTED */ | ||
86 | |||
87 | #define MACEXEC 00100 | ||
88 | #define MACWRITE 00200 | ||
89 | #define MACREAD 00400 | ||
90 | |||
91 | struct xfs_inode; | ||
92 | extern int xfs_mac_iaccess(struct xfs_inode *, mode_t, cred_t *); | ||
93 | |||
94 | #define _MAC_XFS_IACCESS(i,m,c) (xfs_mac_iaccess(i,m,c)) | ||
95 | #define _MAC_VACCESS(v,c,m) (xfs_mac_vaccess(v,c,m)) | ||
96 | #define _MAC_EXISTS xfs_mac_vhaslabel | ||
97 | |||
98 | #else | ||
99 | #define _MAC_XFS_IACCESS(i,m,c) (0) | ||
100 | #define _MAC_VACCESS(v,c,m) (0) | ||
101 | #define _MAC_EXISTS (NULL) | ||
102 | #endif | ||
103 | |||
104 | #endif /* __KERNEL__ */ | ||
105 | |||
106 | #endif /* __XFS_MAC_H__ */ | ||
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 9dfae18d995f..3bed0cf0d8af 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -52,21 +52,19 @@ STATIC void xfs_unmountfs_wait(xfs_mount_t *); | |||
52 | 52 | ||
53 | #ifdef HAVE_PERCPU_SB | 53 | #ifdef HAVE_PERCPU_SB |
54 | STATIC void xfs_icsb_destroy_counters(xfs_mount_t *); | 54 | STATIC void xfs_icsb_destroy_counters(xfs_mount_t *); |
55 | STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, int); | 55 | STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, |
56 | int, int); | ||
56 | STATIC void xfs_icsb_sync_counters(xfs_mount_t *); | 57 | STATIC void xfs_icsb_sync_counters(xfs_mount_t *); |
57 | STATIC int xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t, | 58 | STATIC int xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t, |
58 | int, int); | 59 | int64_t, int); |
59 | STATIC int xfs_icsb_modify_counters_locked(xfs_mount_t *, xfs_sb_field_t, | ||
60 | int, int); | ||
61 | STATIC int xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t); | 60 | STATIC int xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t); |
62 | 61 | ||
63 | #else | 62 | #else |
64 | 63 | ||
65 | #define xfs_icsb_destroy_counters(mp) do { } while (0) | 64 | #define xfs_icsb_destroy_counters(mp) do { } while (0) |
66 | #define xfs_icsb_balance_counter(mp, a, b) do { } while (0) | 65 | #define xfs_icsb_balance_counter(mp, a, b, c) do { } while (0) |
67 | #define xfs_icsb_sync_counters(mp) do { } while (0) | 66 | #define xfs_icsb_sync_counters(mp) do { } while (0) |
68 | #define xfs_icsb_modify_counters(mp, a, b, c) do { } while (0) | 67 | #define xfs_icsb_modify_counters(mp, a, b, c) do { } while (0) |
69 | #define xfs_icsb_modify_counters_locked(mp, a, b, c) do { } while (0) | ||
70 | 68 | ||
71 | #endif | 69 | #endif |
72 | 70 | ||
@@ -545,9 +543,8 @@ xfs_readsb(xfs_mount_t *mp, int flags) | |||
545 | ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); | 543 | ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); |
546 | } | 544 | } |
547 | 545 | ||
548 | xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0); | 546 | /* Initialize per-cpu counters */ |
549 | xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0); | 547 | xfs_icsb_reinit_counters(mp); |
550 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); | ||
551 | 548 | ||
552 | mp->m_sb_bp = bp; | 549 | mp->m_sb_bp = bp; |
553 | xfs_buf_relse(bp); | 550 | xfs_buf_relse(bp); |
@@ -1254,8 +1251,11 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) | |||
1254 | * The SB_LOCK must be held when this routine is called. | 1251 | * The SB_LOCK must be held when this routine is called. |
1255 | */ | 1252 | */ |
1256 | int | 1253 | int |
1257 | xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, | 1254 | xfs_mod_incore_sb_unlocked( |
1258 | int delta, int rsvd) | 1255 | xfs_mount_t *mp, |
1256 | xfs_sb_field_t field, | ||
1257 | int64_t delta, | ||
1258 | int rsvd) | ||
1259 | { | 1259 | { |
1260 | int scounter; /* short counter for 32 bit fields */ | 1260 | int scounter; /* short counter for 32 bit fields */ |
1261 | long long lcounter; /* long counter for 64 bit fields */ | 1261 | long long lcounter; /* long counter for 64 bit fields */ |
@@ -1287,7 +1287,6 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, | |||
1287 | mp->m_sb.sb_ifree = lcounter; | 1287 | mp->m_sb.sb_ifree = lcounter; |
1288 | return 0; | 1288 | return 0; |
1289 | case XFS_SBS_FDBLOCKS: | 1289 | case XFS_SBS_FDBLOCKS: |
1290 | |||
1291 | lcounter = (long long) | 1290 | lcounter = (long long) |
1292 | mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | 1291 | mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); |
1293 | res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); | 1292 | res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); |
@@ -1418,7 +1417,11 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, | |||
1418 | * routine to do the work. | 1417 | * routine to do the work. |
1419 | */ | 1418 | */ |
1420 | int | 1419 | int |
1421 | xfs_mod_incore_sb(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd) | 1420 | xfs_mod_incore_sb( |
1421 | xfs_mount_t *mp, | ||
1422 | xfs_sb_field_t field, | ||
1423 | int64_t delta, | ||
1424 | int rsvd) | ||
1422 | { | 1425 | { |
1423 | unsigned long s; | 1426 | unsigned long s; |
1424 | int status; | 1427 | int status; |
@@ -1485,9 +1488,11 @@ xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd) | |||
1485 | case XFS_SBS_IFREE: | 1488 | case XFS_SBS_IFREE: |
1486 | case XFS_SBS_FDBLOCKS: | 1489 | case XFS_SBS_FDBLOCKS: |
1487 | if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { | 1490 | if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { |
1488 | status = xfs_icsb_modify_counters_locked(mp, | 1491 | XFS_SB_UNLOCK(mp, s); |
1492 | status = xfs_icsb_modify_counters(mp, | ||
1489 | msbp->msb_field, | 1493 | msbp->msb_field, |
1490 | msbp->msb_delta, rsvd); | 1494 | msbp->msb_delta, rsvd); |
1495 | s = XFS_SB_LOCK(mp); | ||
1491 | break; | 1496 | break; |
1492 | } | 1497 | } |
1493 | /* FALLTHROUGH */ | 1498 | /* FALLTHROUGH */ |
@@ -1521,11 +1526,12 @@ xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd) | |||
1521 | case XFS_SBS_IFREE: | 1526 | case XFS_SBS_IFREE: |
1522 | case XFS_SBS_FDBLOCKS: | 1527 | case XFS_SBS_FDBLOCKS: |
1523 | if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { | 1528 | if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { |
1524 | status = | 1529 | XFS_SB_UNLOCK(mp, s); |
1525 | xfs_icsb_modify_counters_locked(mp, | 1530 | status = xfs_icsb_modify_counters(mp, |
1526 | msbp->msb_field, | 1531 | msbp->msb_field, |
1527 | -(msbp->msb_delta), | 1532 | -(msbp->msb_delta), |
1528 | rsvd); | 1533 | rsvd); |
1534 | s = XFS_SB_LOCK(mp); | ||
1529 | break; | 1535 | break; |
1530 | } | 1536 | } |
1531 | /* FALLTHROUGH */ | 1537 | /* FALLTHROUGH */ |
@@ -1733,14 +1739,17 @@ xfs_icsb_cpu_notify( | |||
1733 | memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); | 1739 | memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); |
1734 | break; | 1740 | break; |
1735 | case CPU_ONLINE: | 1741 | case CPU_ONLINE: |
1736 | xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0); | 1742 | xfs_icsb_lock(mp); |
1737 | xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0); | 1743 | xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0); |
1738 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); | 1744 | xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0); |
1745 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0); | ||
1746 | xfs_icsb_unlock(mp); | ||
1739 | break; | 1747 | break; |
1740 | case CPU_DEAD: | 1748 | case CPU_DEAD: |
1741 | /* Disable all the counters, then fold the dead cpu's | 1749 | /* Disable all the counters, then fold the dead cpu's |
1742 | * count into the total on the global superblock and | 1750 | * count into the total on the global superblock and |
1743 | * re-enable the counters. */ | 1751 | * re-enable the counters. */ |
1752 | xfs_icsb_lock(mp); | ||
1744 | s = XFS_SB_LOCK(mp); | 1753 | s = XFS_SB_LOCK(mp); |
1745 | xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT); | 1754 | xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT); |
1746 | xfs_icsb_disable_counter(mp, XFS_SBS_IFREE); | 1755 | xfs_icsb_disable_counter(mp, XFS_SBS_IFREE); |
@@ -1752,10 +1761,14 @@ xfs_icsb_cpu_notify( | |||
1752 | 1761 | ||
1753 | memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); | 1762 | memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); |
1754 | 1763 | ||
1755 | xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED); | 1764 | xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, |
1756 | xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED); | 1765 | XFS_ICSB_SB_LOCKED, 0); |
1757 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, XFS_ICSB_SB_LOCKED); | 1766 | xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, |
1767 | XFS_ICSB_SB_LOCKED, 0); | ||
1768 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, | ||
1769 | XFS_ICSB_SB_LOCKED, 0); | ||
1758 | XFS_SB_UNLOCK(mp, s); | 1770 | XFS_SB_UNLOCK(mp, s); |
1771 | xfs_icsb_unlock(mp); | ||
1759 | break; | 1772 | break; |
1760 | } | 1773 | } |
1761 | 1774 | ||
@@ -1784,6 +1797,9 @@ xfs_icsb_init_counters( | |||
1784 | cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); | 1797 | cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); |
1785 | memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); | 1798 | memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); |
1786 | } | 1799 | } |
1800 | |||
1801 | mutex_init(&mp->m_icsb_mutex); | ||
1802 | |||
1787 | /* | 1803 | /* |
1788 | * start with all counters disabled so that the | 1804 | * start with all counters disabled so that the |
1789 | * initial balance kicks us off correctly | 1805 | * initial balance kicks us off correctly |
@@ -1792,6 +1808,22 @@ xfs_icsb_init_counters( | |||
1792 | return 0; | 1808 | return 0; |
1793 | } | 1809 | } |
1794 | 1810 | ||
1811 | void | ||
1812 | xfs_icsb_reinit_counters( | ||
1813 | xfs_mount_t *mp) | ||
1814 | { | ||
1815 | xfs_icsb_lock(mp); | ||
1816 | /* | ||
1817 | * start with all counters disabled so that the | ||
1818 | * initial balance kicks us off correctly | ||
1819 | */ | ||
1820 | mp->m_icsb_counters = -1; | ||
1821 | xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0); | ||
1822 | xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0); | ||
1823 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0); | ||
1824 | xfs_icsb_unlock(mp); | ||
1825 | } | ||
1826 | |||
1795 | STATIC void | 1827 | STATIC void |
1796 | xfs_icsb_destroy_counters( | 1828 | xfs_icsb_destroy_counters( |
1797 | xfs_mount_t *mp) | 1829 | xfs_mount_t *mp) |
@@ -1800,9 +1832,10 @@ xfs_icsb_destroy_counters( | |||
1800 | unregister_hotcpu_notifier(&mp->m_icsb_notifier); | 1832 | unregister_hotcpu_notifier(&mp->m_icsb_notifier); |
1801 | free_percpu(mp->m_sb_cnts); | 1833 | free_percpu(mp->m_sb_cnts); |
1802 | } | 1834 | } |
1835 | mutex_destroy(&mp->m_icsb_mutex); | ||
1803 | } | 1836 | } |
1804 | 1837 | ||
1805 | STATIC inline void | 1838 | STATIC_INLINE void |
1806 | xfs_icsb_lock_cntr( | 1839 | xfs_icsb_lock_cntr( |
1807 | xfs_icsb_cnts_t *icsbp) | 1840 | xfs_icsb_cnts_t *icsbp) |
1808 | { | 1841 | { |
@@ -1811,7 +1844,7 @@ xfs_icsb_lock_cntr( | |||
1811 | } | 1844 | } |
1812 | } | 1845 | } |
1813 | 1846 | ||
1814 | STATIC inline void | 1847 | STATIC_INLINE void |
1815 | xfs_icsb_unlock_cntr( | 1848 | xfs_icsb_unlock_cntr( |
1816 | xfs_icsb_cnts_t *icsbp) | 1849 | xfs_icsb_cnts_t *icsbp) |
1817 | { | 1850 | { |
@@ -1819,7 +1852,7 @@ xfs_icsb_unlock_cntr( | |||
1819 | } | 1852 | } |
1820 | 1853 | ||
1821 | 1854 | ||
1822 | STATIC inline void | 1855 | STATIC_INLINE void |
1823 | xfs_icsb_lock_all_counters( | 1856 | xfs_icsb_lock_all_counters( |
1824 | xfs_mount_t *mp) | 1857 | xfs_mount_t *mp) |
1825 | { | 1858 | { |
@@ -1832,7 +1865,7 @@ xfs_icsb_lock_all_counters( | |||
1832 | } | 1865 | } |
1833 | } | 1866 | } |
1834 | 1867 | ||
1835 | STATIC inline void | 1868 | STATIC_INLINE void |
1836 | xfs_icsb_unlock_all_counters( | 1869 | xfs_icsb_unlock_all_counters( |
1837 | xfs_mount_t *mp) | 1870 | xfs_mount_t *mp) |
1838 | { | 1871 | { |
@@ -1888,6 +1921,17 @@ xfs_icsb_disable_counter( | |||
1888 | 1921 | ||
1889 | ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); | 1922 | ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); |
1890 | 1923 | ||
1924 | /* | ||
1925 | * If we are already disabled, then there is nothing to do | ||
1926 | * here. We check before locking all the counters to avoid | ||
1927 | * the expensive lock operation when being called in the | ||
1928 | * slow path and the counter is already disabled. This is | ||
1929 | * safe because the only time we set or clear this state is under | ||
1930 | * the m_icsb_mutex. | ||
1931 | */ | ||
1932 | if (xfs_icsb_counter_disabled(mp, field)) | ||
1933 | return 0; | ||
1934 | |||
1891 | xfs_icsb_lock_all_counters(mp); | 1935 | xfs_icsb_lock_all_counters(mp); |
1892 | if (!test_and_set_bit(field, &mp->m_icsb_counters)) { | 1936 | if (!test_and_set_bit(field, &mp->m_icsb_counters)) { |
1893 | /* drain back to superblock */ | 1937 | /* drain back to superblock */ |
@@ -1948,8 +1992,8 @@ xfs_icsb_enable_counter( | |||
1948 | xfs_icsb_unlock_all_counters(mp); | 1992 | xfs_icsb_unlock_all_counters(mp); |
1949 | } | 1993 | } |
1950 | 1994 | ||
1951 | STATIC void | 1995 | void |
1952 | xfs_icsb_sync_counters_int( | 1996 | xfs_icsb_sync_counters_flags( |
1953 | xfs_mount_t *mp, | 1997 | xfs_mount_t *mp, |
1954 | int flags) | 1998 | int flags) |
1955 | { | 1999 | { |
@@ -1981,40 +2025,39 @@ STATIC void | |||
1981 | xfs_icsb_sync_counters( | 2025 | xfs_icsb_sync_counters( |
1982 | xfs_mount_t *mp) | 2026 | xfs_mount_t *mp) |
1983 | { | 2027 | { |
1984 | xfs_icsb_sync_counters_int(mp, 0); | 2028 | xfs_icsb_sync_counters_flags(mp, 0); |
1985 | } | ||
1986 | |||
1987 | /* | ||
1988 | * lazy addition used for things like df, background sb syncs, etc | ||
1989 | */ | ||
1990 | void | ||
1991 | xfs_icsb_sync_counters_lazy( | ||
1992 | xfs_mount_t *mp) | ||
1993 | { | ||
1994 | xfs_icsb_sync_counters_int(mp, XFS_ICSB_LAZY_COUNT); | ||
1995 | } | 2029 | } |
1996 | 2030 | ||
1997 | /* | 2031 | /* |
1998 | * Balance and enable/disable counters as necessary. | 2032 | * Balance and enable/disable counters as necessary. |
1999 | * | 2033 | * |
2000 | * Thresholds for re-enabling counters are somewhat magic. | 2034 | * Thresholds for re-enabling counters are somewhat magic. inode counts are |
2001 | * inode counts are chosen to be the same number as single | 2035 | * chosen to be the same number as single on disk allocation chunk per CPU, and |
2002 | * on disk allocation chunk per CPU, and free blocks is | 2036 | * free blocks is something far enough zero that we aren't going thrash when we |
2003 | * something far enough zero that we aren't going thrash | 2037 | * get near ENOSPC. We also need to supply a minimum we require per cpu to |
2004 | * when we get near ENOSPC. | 2038 | * prevent looping endlessly when xfs_alloc_space asks for more than will |
2039 | * be distributed to a single CPU but each CPU has enough blocks to be | ||
2040 | * reenabled. | ||
2041 | * | ||
2042 | * Note that we can be called when counters are already disabled. | ||
2043 | * xfs_icsb_disable_counter() optimises the counter locking in this case to | ||
2044 | * prevent locking every per-cpu counter needlessly. | ||
2005 | */ | 2045 | */ |
2006 | #define XFS_ICSB_INO_CNTR_REENABLE 64 | 2046 | |
2047 | #define XFS_ICSB_INO_CNTR_REENABLE (uint64_t)64 | ||
2007 | #define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \ | 2048 | #define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \ |
2008 | (512 + XFS_ALLOC_SET_ASIDE(mp)) | 2049 | (uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp)) |
2009 | STATIC void | 2050 | STATIC void |
2010 | xfs_icsb_balance_counter( | 2051 | xfs_icsb_balance_counter( |
2011 | xfs_mount_t *mp, | 2052 | xfs_mount_t *mp, |
2012 | xfs_sb_field_t field, | 2053 | xfs_sb_field_t field, |
2013 | int flags) | 2054 | int flags, |
2055 | int min_per_cpu) | ||
2014 | { | 2056 | { |
2015 | uint64_t count, resid; | 2057 | uint64_t count, resid; |
2016 | int weight = num_online_cpus(); | 2058 | int weight = num_online_cpus(); |
2017 | int s; | 2059 | int s; |
2060 | uint64_t min = (uint64_t)min_per_cpu; | ||
2018 | 2061 | ||
2019 | if (!(flags & XFS_ICSB_SB_LOCKED)) | 2062 | if (!(flags & XFS_ICSB_SB_LOCKED)) |
2020 | s = XFS_SB_LOCK(mp); | 2063 | s = XFS_SB_LOCK(mp); |
@@ -2027,19 +2070,19 @@ xfs_icsb_balance_counter( | |||
2027 | case XFS_SBS_ICOUNT: | 2070 | case XFS_SBS_ICOUNT: |
2028 | count = mp->m_sb.sb_icount; | 2071 | count = mp->m_sb.sb_icount; |
2029 | resid = do_div(count, weight); | 2072 | resid = do_div(count, weight); |
2030 | if (count < XFS_ICSB_INO_CNTR_REENABLE) | 2073 | if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE)) |
2031 | goto out; | 2074 | goto out; |
2032 | break; | 2075 | break; |
2033 | case XFS_SBS_IFREE: | 2076 | case XFS_SBS_IFREE: |
2034 | count = mp->m_sb.sb_ifree; | 2077 | count = mp->m_sb.sb_ifree; |
2035 | resid = do_div(count, weight); | 2078 | resid = do_div(count, weight); |
2036 | if (count < XFS_ICSB_INO_CNTR_REENABLE) | 2079 | if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE)) |
2037 | goto out; | 2080 | goto out; |
2038 | break; | 2081 | break; |
2039 | case XFS_SBS_FDBLOCKS: | 2082 | case XFS_SBS_FDBLOCKS: |
2040 | count = mp->m_sb.sb_fdblocks; | 2083 | count = mp->m_sb.sb_fdblocks; |
2041 | resid = do_div(count, weight); | 2084 | resid = do_div(count, weight); |
2042 | if (count < XFS_ICSB_FDBLK_CNTR_REENABLE(mp)) | 2085 | if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp))) |
2043 | goto out; | 2086 | goto out; |
2044 | break; | 2087 | break; |
2045 | default: | 2088 | default: |
@@ -2054,32 +2097,39 @@ out: | |||
2054 | XFS_SB_UNLOCK(mp, s); | 2097 | XFS_SB_UNLOCK(mp, s); |
2055 | } | 2098 | } |
2056 | 2099 | ||
2057 | STATIC int | 2100 | int |
2058 | xfs_icsb_modify_counters_int( | 2101 | xfs_icsb_modify_counters( |
2059 | xfs_mount_t *mp, | 2102 | xfs_mount_t *mp, |
2060 | xfs_sb_field_t field, | 2103 | xfs_sb_field_t field, |
2061 | int delta, | 2104 | int64_t delta, |
2062 | int rsvd, | 2105 | int rsvd) |
2063 | int flags) | ||
2064 | { | 2106 | { |
2065 | xfs_icsb_cnts_t *icsbp; | 2107 | xfs_icsb_cnts_t *icsbp; |
2066 | long long lcounter; /* long counter for 64 bit fields */ | 2108 | long long lcounter; /* long counter for 64 bit fields */ |
2067 | int cpu, s, locked = 0; | 2109 | int cpu, ret = 0, s; |
2068 | int ret = 0, balance_done = 0; | ||
2069 | 2110 | ||
2111 | might_sleep(); | ||
2070 | again: | 2112 | again: |
2071 | cpu = get_cpu(); | 2113 | cpu = get_cpu(); |
2072 | icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu), | 2114 | icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu); |
2073 | xfs_icsb_lock_cntr(icsbp); | 2115 | |
2116 | /* | ||
2117 | * if the counter is disabled, go to slow path | ||
2118 | */ | ||
2074 | if (unlikely(xfs_icsb_counter_disabled(mp, field))) | 2119 | if (unlikely(xfs_icsb_counter_disabled(mp, field))) |
2075 | goto slow_path; | 2120 | goto slow_path; |
2121 | xfs_icsb_lock_cntr(icsbp); | ||
2122 | if (unlikely(xfs_icsb_counter_disabled(mp, field))) { | ||
2123 | xfs_icsb_unlock_cntr(icsbp); | ||
2124 | goto slow_path; | ||
2125 | } | ||
2076 | 2126 | ||
2077 | switch (field) { | 2127 | switch (field) { |
2078 | case XFS_SBS_ICOUNT: | 2128 | case XFS_SBS_ICOUNT: |
2079 | lcounter = icsbp->icsb_icount; | 2129 | lcounter = icsbp->icsb_icount; |
2080 | lcounter += delta; | 2130 | lcounter += delta; |
2081 | if (unlikely(lcounter < 0)) | 2131 | if (unlikely(lcounter < 0)) |
2082 | goto slow_path; | 2132 | goto balance_counter; |
2083 | icsbp->icsb_icount = lcounter; | 2133 | icsbp->icsb_icount = lcounter; |
2084 | break; | 2134 | break; |
2085 | 2135 | ||
@@ -2087,7 +2137,7 @@ again: | |||
2087 | lcounter = icsbp->icsb_ifree; | 2137 | lcounter = icsbp->icsb_ifree; |
2088 | lcounter += delta; | 2138 | lcounter += delta; |
2089 | if (unlikely(lcounter < 0)) | 2139 | if (unlikely(lcounter < 0)) |
2090 | goto slow_path; | 2140 | goto balance_counter; |
2091 | icsbp->icsb_ifree = lcounter; | 2141 | icsbp->icsb_ifree = lcounter; |
2092 | break; | 2142 | break; |
2093 | 2143 | ||
@@ -2097,7 +2147,7 @@ again: | |||
2097 | lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | 2147 | lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); |
2098 | lcounter += delta; | 2148 | lcounter += delta; |
2099 | if (unlikely(lcounter < 0)) | 2149 | if (unlikely(lcounter < 0)) |
2100 | goto slow_path; | 2150 | goto balance_counter; |
2101 | icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); | 2151 | icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); |
2102 | break; | 2152 | break; |
2103 | default: | 2153 | default: |
@@ -2106,72 +2156,78 @@ again: | |||
2106 | } | 2156 | } |
2107 | xfs_icsb_unlock_cntr(icsbp); | 2157 | xfs_icsb_unlock_cntr(icsbp); |
2108 | put_cpu(); | 2158 | put_cpu(); |
2109 | if (locked) | ||
2110 | XFS_SB_UNLOCK(mp, s); | ||
2111 | return 0; | 2159 | return 0; |
2112 | 2160 | ||
2113 | /* | ||
2114 | * The slow path needs to be run with the SBLOCK | ||
2115 | * held so that we prevent other threads from | ||
2116 | * attempting to run this path at the same time. | ||
2117 | * this provides exclusion for the balancing code, | ||
2118 | * and exclusive fallback if the balance does not | ||
2119 | * provide enough resources to continue in an unlocked | ||
2120 | * manner. | ||
2121 | */ | ||
2122 | slow_path: | 2161 | slow_path: |
2123 | xfs_icsb_unlock_cntr(icsbp); | ||
2124 | put_cpu(); | 2162 | put_cpu(); |
2125 | 2163 | ||
2126 | /* need to hold superblock incase we need | 2164 | /* |
2127 | * to disable a counter */ | 2165 | * serialise with a mutex so we don't burn lots of cpu on |
2128 | if (!(flags & XFS_ICSB_SB_LOCKED)) { | 2166 | * the superblock lock. We still need to hold the superblock |
2129 | s = XFS_SB_LOCK(mp); | 2167 | * lock, however, when we modify the global structures. |
2130 | locked = 1; | 2168 | */ |
2131 | flags |= XFS_ICSB_SB_LOCKED; | 2169 | xfs_icsb_lock(mp); |
2132 | } | 2170 | |
2133 | if (!balance_done) { | 2171 | /* |
2134 | xfs_icsb_balance_counter(mp, field, flags); | 2172 | * Now running atomically. |
2135 | balance_done = 1; | 2173 | * |
2174 | * If the counter is enabled, someone has beaten us to rebalancing. | ||
2175 | * Drop the lock and try again in the fast path.... | ||
2176 | */ | ||
2177 | if (!(xfs_icsb_counter_disabled(mp, field))) { | ||
2178 | xfs_icsb_unlock(mp); | ||
2136 | goto again; | 2179 | goto again; |
2137 | } else { | ||
2138 | /* | ||
2139 | * we might not have enough on this local | ||
2140 | * cpu to allocate for a bulk request. | ||
2141 | * We need to drain this field from all CPUs | ||
2142 | * and disable the counter fastpath | ||
2143 | */ | ||
2144 | xfs_icsb_disable_counter(mp, field); | ||
2145 | } | 2180 | } |
2146 | 2181 | ||
2182 | /* | ||
2183 | * The counter is currently disabled. Because we are | ||
2184 | * running atomically here, we know a rebalance cannot | ||
2185 | * be in progress. Hence we can go straight to operating | ||
2186 | * on the global superblock. We do not call xfs_mod_incore_sb() | ||
2187 | * here even though we need to get the SB_LOCK. Doing so | ||
2188 | * will cause us to re-enter this function and deadlock. | ||
2189 | * Hence we get the SB_LOCK ourselves and then call | ||
2190 | * xfs_mod_incore_sb_unlocked() as the unlocked path operates | ||
2191 | * directly on the global counters. | ||
2192 | */ | ||
2193 | s = XFS_SB_LOCK(mp); | ||
2147 | ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); | 2194 | ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); |
2195 | XFS_SB_UNLOCK(mp, s); | ||
2148 | 2196 | ||
2149 | if (locked) | 2197 | /* |
2150 | XFS_SB_UNLOCK(mp, s); | 2198 | * Now that we've modified the global superblock, we |
2199 | * may be able to re-enable the distributed counters | ||
2200 | * (e.g. lots of space just got freed). After that | ||
2201 | * we are done. | ||
2202 | */ | ||
2203 | if (ret != ENOSPC) | ||
2204 | xfs_icsb_balance_counter(mp, field, 0, 0); | ||
2205 | xfs_icsb_unlock(mp); | ||
2151 | return ret; | 2206 | return ret; |
2152 | } | ||
2153 | 2207 | ||
2154 | STATIC int | 2208 | balance_counter: |
2155 | xfs_icsb_modify_counters( | 2209 | xfs_icsb_unlock_cntr(icsbp); |
2156 | xfs_mount_t *mp, | 2210 | put_cpu(); |
2157 | xfs_sb_field_t field, | ||
2158 | int delta, | ||
2159 | int rsvd) | ||
2160 | { | ||
2161 | return xfs_icsb_modify_counters_int(mp, field, delta, rsvd, 0); | ||
2162 | } | ||
2163 | 2211 | ||
2164 | /* | 2212 | /* |
2165 | * Called when superblock is already locked | 2213 | * We may have multiple threads here if multiple per-cpu |
2166 | */ | 2214 | * counters run dry at the same time. This will mean we can |
2167 | STATIC int | 2215 | * do more balances than strictly necessary but it is not |
2168 | xfs_icsb_modify_counters_locked( | 2216 | * the common slowpath case. |
2169 | xfs_mount_t *mp, | 2217 | */ |
2170 | xfs_sb_field_t field, | 2218 | xfs_icsb_lock(mp); |
2171 | int delta, | 2219 | |
2172 | int rsvd) | 2220 | /* |
2173 | { | 2221 | * running atomically. |
2174 | return xfs_icsb_modify_counters_int(mp, field, delta, | 2222 | * |
2175 | rsvd, XFS_ICSB_SB_LOCKED); | 2223 | * This will leave the counter in the correct state for future |
2224 | * accesses. After the rebalance, we simply try again and our retry | ||
2225 | * will either succeed through the fast path or slow path without | ||
2226 | * another balance operation being required. | ||
2227 | */ | ||
2228 | xfs_icsb_balance_counter(mp, field, 0, delta); | ||
2229 | xfs_icsb_unlock(mp); | ||
2230 | goto again; | ||
2176 | } | 2231 | } |
2232 | |||
2177 | #endif | 2233 | #endif |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index e5f396ff9a3d..82304b94646d 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #ifndef __XFS_MOUNT_H__ | 18 | #ifndef __XFS_MOUNT_H__ |
19 | #define __XFS_MOUNT_H__ | 19 | #define __XFS_MOUNT_H__ |
20 | 20 | ||
21 | |||
21 | typedef struct xfs_trans_reservations { | 22 | typedef struct xfs_trans_reservations { |
22 | uint tr_write; /* extent alloc trans */ | 23 | uint tr_write; /* extent alloc trans */ |
23 | uint tr_itruncate; /* truncate trans */ | 24 | uint tr_itruncate; /* truncate trans */ |
@@ -306,11 +307,13 @@ typedef struct xfs_icsb_cnts { | |||
306 | #define XFS_ICSB_LAZY_COUNT (1 << 1) /* accuracy not needed */ | 307 | #define XFS_ICSB_LAZY_COUNT (1 << 1) /* accuracy not needed */ |
307 | 308 | ||
308 | extern int xfs_icsb_init_counters(struct xfs_mount *); | 309 | extern int xfs_icsb_init_counters(struct xfs_mount *); |
309 | extern void xfs_icsb_sync_counters_lazy(struct xfs_mount *); | 310 | extern void xfs_icsb_reinit_counters(struct xfs_mount *); |
311 | extern void xfs_icsb_sync_counters_flags(struct xfs_mount *, int); | ||
310 | 312 | ||
311 | #else | 313 | #else |
312 | #define xfs_icsb_init_counters(mp) (0) | 314 | #define xfs_icsb_init_counters(mp) (0) |
313 | #define xfs_icsb_sync_counters_lazy(mp) do { } while (0) | 315 | #define xfs_icsb_reinit_counters(mp) do { } while (0) |
316 | #define xfs_icsb_sync_counters_flags(mp, flags) do { } while (0) | ||
314 | #endif | 317 | #endif |
315 | 318 | ||
316 | typedef struct xfs_mount { | 319 | typedef struct xfs_mount { |
@@ -419,6 +422,7 @@ typedef struct xfs_mount { | |||
419 | xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */ | 422 | xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */ |
420 | unsigned long m_icsb_counters; /* disabled per-cpu counters */ | 423 | unsigned long m_icsb_counters; /* disabled per-cpu counters */ |
421 | struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */ | 424 | struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */ |
425 | struct mutex m_icsb_mutex; /* balancer sync lock */ | ||
422 | #endif | 426 | #endif |
423 | } xfs_mount_t; | 427 | } xfs_mount_t; |
424 | 428 | ||
@@ -563,11 +567,32 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d) | |||
563 | } | 567 | } |
564 | 568 | ||
565 | /* | 569 | /* |
570 | * Per-cpu superblock locking functions | ||
571 | */ | ||
572 | #ifdef HAVE_PERCPU_SB | ||
573 | STATIC_INLINE void | ||
574 | xfs_icsb_lock(xfs_mount_t *mp) | ||
575 | { | ||
576 | mutex_lock(&mp->m_icsb_mutex); | ||
577 | } | ||
578 | |||
579 | STATIC_INLINE void | ||
580 | xfs_icsb_unlock(xfs_mount_t *mp) | ||
581 | { | ||
582 | mutex_unlock(&mp->m_icsb_mutex); | ||
583 | } | ||
584 | #else | ||
585 | #define xfs_icsb_lock(mp) | ||
586 | #define xfs_icsb_unlock(mp) | ||
587 | #endif | ||
588 | |||
589 | /* | ||
566 | * This structure is for use by the xfs_mod_incore_sb_batch() routine. | 590 | * This structure is for use by the xfs_mod_incore_sb_batch() routine. |
591 | * xfs_growfs can specify a few fields which are more than int limit | ||
567 | */ | 592 | */ |
568 | typedef struct xfs_mod_sb { | 593 | typedef struct xfs_mod_sb { |
569 | xfs_sb_field_t msb_field; /* Field to modify, see below */ | 594 | xfs_sb_field_t msb_field; /* Field to modify, see below */ |
570 | int msb_delta; /* Change to make to specified field */ | 595 | int64_t msb_delta; /* Change to make to specified field */ |
571 | } xfs_mod_sb_t; | 596 | } xfs_mod_sb_t; |
572 | 597 | ||
573 | #define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock)) | 598 | #define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock)) |
@@ -585,17 +610,17 @@ extern int xfs_unmountfs(xfs_mount_t *, struct cred *); | |||
585 | extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *); | 610 | extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *); |
586 | extern int xfs_unmountfs_writesb(xfs_mount_t *); | 611 | extern int xfs_unmountfs_writesb(xfs_mount_t *); |
587 | extern int xfs_unmount_flush(xfs_mount_t *, int); | 612 | extern int xfs_unmount_flush(xfs_mount_t *, int); |
588 | extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int, int); | 613 | extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int); |
589 | extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t, | 614 | extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t, |
590 | int, int); | 615 | int64_t, int); |
591 | extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, | 616 | extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, |
592 | uint, int); | 617 | uint, int); |
593 | extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); | 618 | extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); |
594 | extern int xfs_readsb(xfs_mount_t *, int); | 619 | extern int xfs_readsb(xfs_mount_t *, int); |
595 | extern void xfs_freesb(xfs_mount_t *); | 620 | extern void xfs_freesb(xfs_mount_t *); |
596 | extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); | 621 | extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); |
597 | extern int xfs_syncsub(xfs_mount_t *, int, int, int *); | 622 | extern int xfs_syncsub(xfs_mount_t *, int, int *); |
598 | extern int xfs_sync_inodes(xfs_mount_t *, int, int, int *); | 623 | extern int xfs_sync_inodes(xfs_mount_t *, int, int *); |
599 | extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *, | 624 | extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *, |
600 | xfs_agnumber_t); | 625 | xfs_agnumber_t); |
601 | extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t); | 626 | extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t); |
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index d98171deaa1c..4c6573d784cd 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c | |||
@@ -565,7 +565,7 @@ xfs_rename( | |||
565 | IHOLD(target_ip); | 565 | IHOLD(target_ip); |
566 | IHOLD(src_ip); | 566 | IHOLD(src_ip); |
567 | 567 | ||
568 | error = xfs_bmap_finish(&tp, &free_list, first_block, &committed); | 568 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
569 | if (error) { | 569 | if (error) { |
570 | xfs_bmap_cancel(&free_list); | 570 | xfs_bmap_cancel(&free_list); |
571 | xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | | 571 | xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | |
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 880c73271c05..6fff19dc3cf9 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c | |||
@@ -147,7 +147,7 @@ xfs_growfs_rt_alloc( | |||
147 | /* | 147 | /* |
148 | * Free any blocks freed up in the transaction, then commit. | 148 | * Free any blocks freed up in the transaction, then commit. |
149 | */ | 149 | */ |
150 | error = xfs_bmap_finish(&tp, &flist, firstblock, &committed); | 150 | error = xfs_bmap_finish(&tp, &flist, &committed); |
151 | if (error) | 151 | if (error) |
152 | goto error_exit; | 152 | goto error_exit; |
153 | xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); | 153 | xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); |
@@ -913,57 +913,6 @@ xfs_rtcheck_alloc_range( | |||
913 | } | 913 | } |
914 | #endif | 914 | #endif |
915 | 915 | ||
916 | #ifdef DEBUG | ||
917 | /* | ||
918 | * Check whether the given block in the bitmap has the given value. | ||
919 | */ | ||
920 | STATIC int /* 1 for matches, 0 for not */ | ||
921 | xfs_rtcheck_bit( | ||
922 | xfs_mount_t *mp, /* file system mount structure */ | ||
923 | xfs_trans_t *tp, /* transaction pointer */ | ||
924 | xfs_rtblock_t start, /* bit (block) to check */ | ||
925 | int val) /* 1 for free, 0 for allocated */ | ||
926 | { | ||
927 | int bit; /* bit number in the word */ | ||
928 | xfs_rtblock_t block; /* bitmap block number */ | ||
929 | xfs_buf_t *bp; /* buf for the block */ | ||
930 | xfs_rtword_t *bufp; /* pointer into the buffer */ | ||
931 | /* REFERENCED */ | ||
932 | int error; /* error value */ | ||
933 | xfs_rtword_t wdiff; /* difference between bit & expected */ | ||
934 | int word; /* word number in the buffer */ | ||
935 | xfs_rtword_t wval; /* word value from buffer */ | ||
936 | |||
937 | block = XFS_BITTOBLOCK(mp, start); | ||
938 | error = xfs_rtbuf_get(mp, tp, block, 0, &bp); | ||
939 | bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp); | ||
940 | word = XFS_BITTOWORD(mp, start); | ||
941 | bit = (int)(start & (XFS_NBWORD - 1)); | ||
942 | wval = bufp[word]; | ||
943 | xfs_trans_brelse(tp, bp); | ||
944 | wdiff = (wval ^ -val) & ((xfs_rtword_t)1 << bit); | ||
945 | return !wdiff; | ||
946 | } | ||
947 | #endif /* DEBUG */ | ||
948 | |||
949 | #if 0 | ||
950 | /* | ||
951 | * Check that the given extent (block range) is free already. | ||
952 | */ | ||
953 | STATIC int /* error */ | ||
954 | xfs_rtcheck_free_range( | ||
955 | xfs_mount_t *mp, /* file system mount point */ | ||
956 | xfs_trans_t *tp, /* transaction pointer */ | ||
957 | xfs_rtblock_t bno, /* starting block number of extent */ | ||
958 | xfs_extlen_t len, /* length of extent */ | ||
959 | int *stat) /* out: 1 for free, 0 for not */ | ||
960 | { | ||
961 | xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */ | ||
962 | |||
963 | return xfs_rtcheck_range(mp, tp, bno, len, 1, &new, stat); | ||
964 | } | ||
965 | #endif | ||
966 | |||
967 | /* | 916 | /* |
968 | * Check that the given range is either all allocated (val = 0) or | 917 | * Check that the given range is either all allocated (val = 0) or |
969 | * all free (val = 1). | 918 | * all free (val = 1). |
@@ -2382,60 +2331,3 @@ xfs_rtpick_extent( | |||
2382 | *pick = b; | 2331 | *pick = b; |
2383 | return 0; | 2332 | return 0; |
2384 | } | 2333 | } |
2385 | |||
2386 | #ifdef DEBUG | ||
2387 | /* | ||
2388 | * Debug code: print out the value of a range in the bitmap. | ||
2389 | */ | ||
2390 | void | ||
2391 | xfs_rtprint_range( | ||
2392 | xfs_mount_t *mp, /* file system mount structure */ | ||
2393 | xfs_trans_t *tp, /* transaction pointer */ | ||
2394 | xfs_rtblock_t start, /* starting block to print */ | ||
2395 | xfs_extlen_t len) /* length to print */ | ||
2396 | { | ||
2397 | xfs_extlen_t i; /* block number in the extent */ | ||
2398 | |||
2399 | cmn_err(CE_DEBUG, "%Ld: ", (long long)start); | ||
2400 | for (i = 0; i < len; i++) | ||
2401 | cmn_err(CE_DEBUG, "%d", xfs_rtcheck_bit(mp, tp, start + i, 1)); | ||
2402 | cmn_err(CE_DEBUG, "\n"); | ||
2403 | } | ||
2404 | |||
2405 | /* | ||
2406 | * Debug code: print the summary file. | ||
2407 | */ | ||
2408 | void | ||
2409 | xfs_rtprint_summary( | ||
2410 | xfs_mount_t *mp, /* file system mount structure */ | ||
2411 | xfs_trans_t *tp) /* transaction pointer */ | ||
2412 | { | ||
2413 | xfs_suminfo_t c; /* summary data */ | ||
2414 | xfs_rtblock_t i; /* bitmap block number */ | ||
2415 | int l; /* summary information level */ | ||
2416 | int p; /* flag for printed anything */ | ||
2417 | xfs_fsblock_t sb; /* summary block number */ | ||
2418 | xfs_buf_t *sumbp; /* summary block buffer */ | ||
2419 | |||
2420 | sumbp = NULL; | ||
2421 | for (l = 0; l < mp->m_rsumlevels; l++) { | ||
2422 | for (p = 0, i = 0; i < mp->m_sb.sb_rbmblocks; i++) { | ||
2423 | (void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c); | ||
2424 | if (c) { | ||
2425 | if (!p) { | ||
2426 | cmn_err(CE_DEBUG, "%Ld-%Ld:", 1LL << l, | ||
2427 | XFS_RTMIN((1LL << l) + | ||
2428 | ((1LL << l) - 1LL), | ||
2429 | mp->m_sb.sb_rextents)); | ||
2430 | p = 1; | ||
2431 | } | ||
2432 | cmn_err(CE_DEBUG, " %Ld:%d", (long long)i, c); | ||
2433 | } | ||
2434 | } | ||
2435 | if (p) | ||
2436 | cmn_err(CE_DEBUG, "\n"); | ||
2437 | } | ||
2438 | if (sumbp) | ||
2439 | xfs_trans_brelse(tp, sumbp); | ||
2440 | } | ||
2441 | #endif /* DEBUG */ | ||
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h index 0e0b4d2ec202..799c1f871263 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h | |||
@@ -134,24 +134,6 @@ xfs_rtpick_extent( | |||
134 | xfs_rtblock_t *pick); /* result rt extent */ | 134 | xfs_rtblock_t *pick); /* result rt extent */ |
135 | 135 | ||
136 | /* | 136 | /* |
137 | * Debug code: print out the value of a range in the bitmap. | ||
138 | */ | ||
139 | void | ||
140 | xfs_rtprint_range( | ||
141 | struct xfs_mount *mp, /* file system mount structure */ | ||
142 | struct xfs_trans *tp, /* transaction pointer */ | ||
143 | xfs_rtblock_t start, /* starting block to print */ | ||
144 | xfs_extlen_t len); /* length to print */ | ||
145 | |||
146 | /* | ||
147 | * Debug code: print the summary file. | ||
148 | */ | ||
149 | void | ||
150 | xfs_rtprint_summary( | ||
151 | struct xfs_mount *mp, /* file system mount structure */ | ||
152 | struct xfs_trans *tp); /* transaction pointer */ | ||
153 | |||
154 | /* | ||
155 | * Grow the realtime area of the filesystem. | 137 | * Grow the realtime area of the filesystem. |
156 | */ | 138 | */ |
157 | int | 139 | int |
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index defb2febaaf5..1ea7c0ca6ae0 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include "xfs_attr.h" | 42 | #include "xfs_attr.h" |
43 | #include "xfs_bmap.h" | 43 | #include "xfs_bmap.h" |
44 | #include "xfs_acl.h" | 44 | #include "xfs_acl.h" |
45 | #include "xfs_mac.h" | ||
46 | #include "xfs_error.h" | 45 | #include "xfs_error.h" |
47 | #include "xfs_buf_item.h" | 46 | #include "xfs_buf_item.h" |
48 | #include "xfs_rw.h" | 47 | #include "xfs_rw.h" |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index ee2721e0de4d..301ff9445b6f 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -339,7 +339,7 @@ xfs_trans_reserve( | |||
339 | */ | 339 | */ |
340 | if (blocks > 0) { | 340 | if (blocks > 0) { |
341 | error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS, | 341 | error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS, |
342 | -blocks, rsvd); | 342 | -((int64_t)blocks), rsvd); |
343 | if (error != 0) { | 343 | if (error != 0) { |
344 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | 344 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
345 | return (XFS_ERROR(ENOSPC)); | 345 | return (XFS_ERROR(ENOSPC)); |
@@ -380,7 +380,7 @@ xfs_trans_reserve( | |||
380 | */ | 380 | */ |
381 | if (rtextents > 0) { | 381 | if (rtextents > 0) { |
382 | error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS, | 382 | error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS, |
383 | -rtextents, rsvd); | 383 | -((int64_t)rtextents), rsvd); |
384 | if (error) { | 384 | if (error) { |
385 | error = XFS_ERROR(ENOSPC); | 385 | error = XFS_ERROR(ENOSPC); |
386 | goto undo_log; | 386 | goto undo_log; |
@@ -410,7 +410,7 @@ undo_log: | |||
410 | undo_blocks: | 410 | undo_blocks: |
411 | if (blocks > 0) { | 411 | if (blocks > 0) { |
412 | (void) xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS, | 412 | (void) xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS, |
413 | blocks, rsvd); | 413 | (int64_t)blocks, rsvd); |
414 | tp->t_blk_res = 0; | 414 | tp->t_blk_res = 0; |
415 | } | 415 | } |
416 | 416 | ||
@@ -432,7 +432,7 @@ void | |||
432 | xfs_trans_mod_sb( | 432 | xfs_trans_mod_sb( |
433 | xfs_trans_t *tp, | 433 | xfs_trans_t *tp, |
434 | uint field, | 434 | uint field, |
435 | long delta) | 435 | int64_t delta) |
436 | { | 436 | { |
437 | 437 | ||
438 | switch (field) { | 438 | switch (field) { |
@@ -663,62 +663,62 @@ xfs_trans_unreserve_and_mod_sb( | |||
663 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) { | 663 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) { |
664 | if (tp->t_icount_delta != 0) { | 664 | if (tp->t_icount_delta != 0) { |
665 | msbp->msb_field = XFS_SBS_ICOUNT; | 665 | msbp->msb_field = XFS_SBS_ICOUNT; |
666 | msbp->msb_delta = (int)tp->t_icount_delta; | 666 | msbp->msb_delta = tp->t_icount_delta; |
667 | msbp++; | 667 | msbp++; |
668 | } | 668 | } |
669 | if (tp->t_ifree_delta != 0) { | 669 | if (tp->t_ifree_delta != 0) { |
670 | msbp->msb_field = XFS_SBS_IFREE; | 670 | msbp->msb_field = XFS_SBS_IFREE; |
671 | msbp->msb_delta = (int)tp->t_ifree_delta; | 671 | msbp->msb_delta = tp->t_ifree_delta; |
672 | msbp++; | 672 | msbp++; |
673 | } | 673 | } |
674 | if (tp->t_fdblocks_delta != 0) { | 674 | if (tp->t_fdblocks_delta != 0) { |
675 | msbp->msb_field = XFS_SBS_FDBLOCKS; | 675 | msbp->msb_field = XFS_SBS_FDBLOCKS; |
676 | msbp->msb_delta = (int)tp->t_fdblocks_delta; | 676 | msbp->msb_delta = tp->t_fdblocks_delta; |
677 | msbp++; | 677 | msbp++; |
678 | } | 678 | } |
679 | if (tp->t_frextents_delta != 0) { | 679 | if (tp->t_frextents_delta != 0) { |
680 | msbp->msb_field = XFS_SBS_FREXTENTS; | 680 | msbp->msb_field = XFS_SBS_FREXTENTS; |
681 | msbp->msb_delta = (int)tp->t_frextents_delta; | 681 | msbp->msb_delta = tp->t_frextents_delta; |
682 | msbp++; | 682 | msbp++; |
683 | } | 683 | } |
684 | if (tp->t_dblocks_delta != 0) { | 684 | if (tp->t_dblocks_delta != 0) { |
685 | msbp->msb_field = XFS_SBS_DBLOCKS; | 685 | msbp->msb_field = XFS_SBS_DBLOCKS; |
686 | msbp->msb_delta = (int)tp->t_dblocks_delta; | 686 | msbp->msb_delta = tp->t_dblocks_delta; |
687 | msbp++; | 687 | msbp++; |
688 | } | 688 | } |
689 | if (tp->t_agcount_delta != 0) { | 689 | if (tp->t_agcount_delta != 0) { |
690 | msbp->msb_field = XFS_SBS_AGCOUNT; | 690 | msbp->msb_field = XFS_SBS_AGCOUNT; |
691 | msbp->msb_delta = (int)tp->t_agcount_delta; | 691 | msbp->msb_delta = tp->t_agcount_delta; |
692 | msbp++; | 692 | msbp++; |
693 | } | 693 | } |
694 | if (tp->t_imaxpct_delta != 0) { | 694 | if (tp->t_imaxpct_delta != 0) { |
695 | msbp->msb_field = XFS_SBS_IMAX_PCT; | 695 | msbp->msb_field = XFS_SBS_IMAX_PCT; |
696 | msbp->msb_delta = (int)tp->t_imaxpct_delta; | 696 | msbp->msb_delta = tp->t_imaxpct_delta; |
697 | msbp++; | 697 | msbp++; |
698 | } | 698 | } |
699 | if (tp->t_rextsize_delta != 0) { | 699 | if (tp->t_rextsize_delta != 0) { |
700 | msbp->msb_field = XFS_SBS_REXTSIZE; | 700 | msbp->msb_field = XFS_SBS_REXTSIZE; |
701 | msbp->msb_delta = (int)tp->t_rextsize_delta; | 701 | msbp->msb_delta = tp->t_rextsize_delta; |
702 | msbp++; | 702 | msbp++; |
703 | } | 703 | } |
704 | if (tp->t_rbmblocks_delta != 0) { | 704 | if (tp->t_rbmblocks_delta != 0) { |
705 | msbp->msb_field = XFS_SBS_RBMBLOCKS; | 705 | msbp->msb_field = XFS_SBS_RBMBLOCKS; |
706 | msbp->msb_delta = (int)tp->t_rbmblocks_delta; | 706 | msbp->msb_delta = tp->t_rbmblocks_delta; |
707 | msbp++; | 707 | msbp++; |
708 | } | 708 | } |
709 | if (tp->t_rblocks_delta != 0) { | 709 | if (tp->t_rblocks_delta != 0) { |
710 | msbp->msb_field = XFS_SBS_RBLOCKS; | 710 | msbp->msb_field = XFS_SBS_RBLOCKS; |
711 | msbp->msb_delta = (int)tp->t_rblocks_delta; | 711 | msbp->msb_delta = tp->t_rblocks_delta; |
712 | msbp++; | 712 | msbp++; |
713 | } | 713 | } |
714 | if (tp->t_rextents_delta != 0) { | 714 | if (tp->t_rextents_delta != 0) { |
715 | msbp->msb_field = XFS_SBS_REXTENTS; | 715 | msbp->msb_field = XFS_SBS_REXTENTS; |
716 | msbp->msb_delta = (int)tp->t_rextents_delta; | 716 | msbp->msb_delta = tp->t_rextents_delta; |
717 | msbp++; | 717 | msbp++; |
718 | } | 718 | } |
719 | if (tp->t_rextslog_delta != 0) { | 719 | if (tp->t_rextslog_delta != 0) { |
720 | msbp->msb_field = XFS_SBS_REXTSLOG; | 720 | msbp->msb_field = XFS_SBS_REXTSLOG; |
721 | msbp->msb_delta = (int)tp->t_rextslog_delta; | 721 | msbp->msb_delta = tp->t_rextslog_delta; |
722 | msbp++; | 722 | msbp++; |
723 | } | 723 | } |
724 | } | 724 | } |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index c68e00105d23..f1d7ab236726 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -39,13 +39,9 @@ typedef struct xfs_trans_header { | |||
39 | /* | 39 | /* |
40 | * Log item types. | 40 | * Log item types. |
41 | */ | 41 | */ |
42 | #define XFS_LI_5_3_BUF 0x1234 /* v1 bufs, 1-block inode buffers */ | ||
43 | #define XFS_LI_5_3_INODE 0x1235 /* 1-block inode buffers */ | ||
44 | #define XFS_LI_EFI 0x1236 | 42 | #define XFS_LI_EFI 0x1236 |
45 | #define XFS_LI_EFD 0x1237 | 43 | #define XFS_LI_EFD 0x1237 |
46 | #define XFS_LI_IUNLINK 0x1238 | 44 | #define XFS_LI_IUNLINK 0x1238 |
47 | #define XFS_LI_6_1_INODE 0x1239 /* 4K non-aligned inode bufs */ | ||
48 | #define XFS_LI_6_1_BUF 0x123a /* v1, 4K inode buffers */ | ||
49 | #define XFS_LI_INODE 0x123b /* aligned ino chunks, var-size ibufs */ | 45 | #define XFS_LI_INODE 0x123b /* aligned ino chunks, var-size ibufs */ |
50 | #define XFS_LI_BUF 0x123c /* v2 bufs, variable sized inode bufs */ | 46 | #define XFS_LI_BUF 0x123c /* v2 bufs, variable sized inode bufs */ |
51 | #define XFS_LI_DQUOT 0x123d | 47 | #define XFS_LI_DQUOT 0x123d |
@@ -354,25 +350,25 @@ typedef struct xfs_trans { | |||
354 | xfs_trans_callback_t t_callback; /* transaction callback */ | 350 | xfs_trans_callback_t t_callback; /* transaction callback */ |
355 | void *t_callarg; /* callback arg */ | 351 | void *t_callarg; /* callback arg */ |
356 | unsigned int t_flags; /* misc flags */ | 352 | unsigned int t_flags; /* misc flags */ |
357 | long t_icount_delta; /* superblock icount change */ | 353 | int64_t t_icount_delta; /* superblock icount change */ |
358 | long t_ifree_delta; /* superblock ifree change */ | 354 | int64_t t_ifree_delta; /* superblock ifree change */ |
359 | long t_fdblocks_delta; /* superblock fdblocks chg */ | 355 | int64_t t_fdblocks_delta; /* superblock fdblocks chg */ |
360 | long t_res_fdblocks_delta; /* on-disk only chg */ | 356 | int64_t t_res_fdblocks_delta; /* on-disk only chg */ |
361 | long t_frextents_delta;/* superblock freextents chg*/ | 357 | int64_t t_frextents_delta;/* superblock freextents chg*/ |
362 | long t_res_frextents_delta; /* on-disk only chg */ | 358 | int64_t t_res_frextents_delta; /* on-disk only chg */ |
363 | #ifdef DEBUG | 359 | #ifdef DEBUG |
364 | long t_ag_freeblks_delta; /* debugging counter */ | 360 | int64_t t_ag_freeblks_delta; /* debugging counter */ |
365 | long t_ag_flist_delta; /* debugging counter */ | 361 | int64_t t_ag_flist_delta; /* debugging counter */ |
366 | long t_ag_btree_delta; /* debugging counter */ | 362 | int64_t t_ag_btree_delta; /* debugging counter */ |
367 | #endif | 363 | #endif |
368 | long t_dblocks_delta;/* superblock dblocks change */ | 364 | int64_t t_dblocks_delta;/* superblock dblocks change */ |
369 | long t_agcount_delta;/* superblock agcount change */ | 365 | int64_t t_agcount_delta;/* superblock agcount change */ |
370 | long t_imaxpct_delta;/* superblock imaxpct change */ | 366 | int64_t t_imaxpct_delta;/* superblock imaxpct change */ |
371 | long t_rextsize_delta;/* superblock rextsize chg */ | 367 | int64_t t_rextsize_delta;/* superblock rextsize chg */ |
372 | long t_rbmblocks_delta;/* superblock rbmblocks chg */ | 368 | int64_t t_rbmblocks_delta;/* superblock rbmblocks chg */ |
373 | long t_rblocks_delta;/* superblock rblocks change */ | 369 | int64_t t_rblocks_delta;/* superblock rblocks change */ |
374 | long t_rextents_delta;/* superblocks rextents chg */ | 370 | int64_t t_rextents_delta;/* superblocks rextents chg */ |
375 | long t_rextslog_delta;/* superblocks rextslog chg */ | 371 | int64_t t_rextslog_delta;/* superblocks rextslog chg */ |
376 | unsigned int t_items_free; /* log item descs free */ | 372 | unsigned int t_items_free; /* log item descs free */ |
377 | xfs_log_item_chunk_t t_items; /* first log item desc chunk */ | 373 | xfs_log_item_chunk_t t_items; /* first log item desc chunk */ |
378 | xfs_trans_header_t t_header; /* header for in-log trans */ | 374 | xfs_trans_header_t t_header; /* header for in-log trans */ |
@@ -936,9 +932,9 @@ typedef struct xfs_trans { | |||
936 | #define xfs_trans_set_sync(tp) ((tp)->t_flags |= XFS_TRANS_SYNC) | 932 | #define xfs_trans_set_sync(tp) ((tp)->t_flags |= XFS_TRANS_SYNC) |
937 | 933 | ||
938 | #ifdef DEBUG | 934 | #ifdef DEBUG |
939 | #define xfs_trans_agblocks_delta(tp, d) ((tp)->t_ag_freeblks_delta += (long)d) | 935 | #define xfs_trans_agblocks_delta(tp, d) ((tp)->t_ag_freeblks_delta += (int64_t)d) |
940 | #define xfs_trans_agflist_delta(tp, d) ((tp)->t_ag_flist_delta += (long)d) | 936 | #define xfs_trans_agflist_delta(tp, d) ((tp)->t_ag_flist_delta += (int64_t)d) |
941 | #define xfs_trans_agbtree_delta(tp, d) ((tp)->t_ag_btree_delta += (long)d) | 937 | #define xfs_trans_agbtree_delta(tp, d) ((tp)->t_ag_btree_delta += (int64_t)d) |
942 | #else | 938 | #else |
943 | #define xfs_trans_agblocks_delta(tp, d) | 939 | #define xfs_trans_agblocks_delta(tp, d) |
944 | #define xfs_trans_agflist_delta(tp, d) | 940 | #define xfs_trans_agflist_delta(tp, d) |
@@ -954,7 +950,7 @@ xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint); | |||
954 | xfs_trans_t *xfs_trans_dup(xfs_trans_t *); | 950 | xfs_trans_t *xfs_trans_dup(xfs_trans_t *); |
955 | int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint, | 951 | int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint, |
956 | uint, uint); | 952 | uint, uint); |
957 | void xfs_trans_mod_sb(xfs_trans_t *, uint, long); | 953 | void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t); |
958 | struct xfs_buf *xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t, | 954 | struct xfs_buf *xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t, |
959 | int, uint); | 955 | int, uint); |
960 | int xfs_trans_read_buf(struct xfs_mount *, xfs_trans_t *, | 956 | int xfs_trans_read_buf(struct xfs_mount *, xfs_trans_t *, |
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index fc39b166d403..ceb4f6e99960 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c | |||
@@ -90,7 +90,7 @@ xfs_trans_push_ail( | |||
90 | int flush_log; | 90 | int flush_log; |
91 | SPLDECL(s); | 91 | SPLDECL(s); |
92 | 92 | ||
93 | #define XFS_TRANS_PUSH_AIL_RESTARTS 10 | 93 | #define XFS_TRANS_PUSH_AIL_RESTARTS 1000 |
94 | 94 | ||
95 | AIL_LOCK(mp,s); | 95 | AIL_LOCK(mp,s); |
96 | lip = xfs_trans_first_ail(mp, &gen); | 96 | lip = xfs_trans_first_ail(mp, &gen); |
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 62336a4cc5a4..29f72f613782 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c | |||
@@ -640,7 +640,7 @@ xfs_quiesce_fs( | |||
640 | * we can write the unmount record. | 640 | * we can write the unmount record. |
641 | */ | 641 | */ |
642 | do { | 642 | do { |
643 | xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL); | 643 | xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, NULL); |
644 | pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1); | 644 | pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1); |
645 | if (!pincount) { | 645 | if (!pincount) { |
646 | delay(50); | 646 | delay(50); |
@@ -806,7 +806,7 @@ xfs_statvfs( | |||
806 | 806 | ||
807 | statp->f_type = XFS_SB_MAGIC; | 807 | statp->f_type = XFS_SB_MAGIC; |
808 | 808 | ||
809 | xfs_icsb_sync_counters_lazy(mp); | 809 | xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT); |
810 | s = XFS_SB_LOCK(mp); | 810 | s = XFS_SB_LOCK(mp); |
811 | statp->f_bsize = sbp->sb_blocksize; | 811 | statp->f_bsize = sbp->sb_blocksize; |
812 | lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0; | 812 | lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0; |
@@ -872,6 +872,10 @@ xfs_statvfs( | |||
872 | * this by simply making sure the log gets flushed | 872 | * this by simply making sure the log gets flushed |
873 | * if SYNC_BDFLUSH is set, and by actually writing it | 873 | * if SYNC_BDFLUSH is set, and by actually writing it |
874 | * out otherwise. | 874 | * out otherwise. |
875 | * SYNC_IOWAIT - The caller wants us to wait for all data I/O to complete | ||
876 | * before we return (including direct I/O). Forms the drain | ||
877 | * side of the write barrier needed to safely quiesce the | ||
878 | * filesystem. | ||
875 | * | 879 | * |
876 | */ | 880 | */ |
877 | /*ARGSUSED*/ | 881 | /*ARGSUSED*/ |
@@ -883,27 +887,20 @@ xfs_sync( | |||
883 | { | 887 | { |
884 | xfs_mount_t *mp = XFS_BHVTOM(bdp); | 888 | xfs_mount_t *mp = XFS_BHVTOM(bdp); |
885 | 889 | ||
886 | if (unlikely(flags == SYNC_QUIESCE)) | 890 | return xfs_syncsub(mp, flags, NULL); |
887 | return xfs_quiesce_fs(mp); | ||
888 | else | ||
889 | return xfs_syncsub(mp, flags, 0, NULL); | ||
890 | } | 891 | } |
891 | 892 | ||
892 | /* | 893 | /* |
893 | * xfs sync routine for internal use | 894 | * xfs sync routine for internal use |
894 | * | 895 | * |
895 | * This routine supports all of the flags defined for the generic vfs_sync | 896 | * This routine supports all of the flags defined for the generic vfs_sync |
896 | * interface as explained above under xfs_sync. In the interests of not | 897 | * interface as explained above under xfs_sync. |
897 | * changing interfaces within the 6.5 family, additional internally- | ||
898 | * required functions are specified within a separate xflags parameter, | ||
899 | * only available by calling this routine. | ||
900 | * | 898 | * |
901 | */ | 899 | */ |
902 | int | 900 | int |
903 | xfs_sync_inodes( | 901 | xfs_sync_inodes( |
904 | xfs_mount_t *mp, | 902 | xfs_mount_t *mp, |
905 | int flags, | 903 | int flags, |
906 | int xflags, | ||
907 | int *bypassed) | 904 | int *bypassed) |
908 | { | 905 | { |
909 | xfs_inode_t *ip = NULL; | 906 | xfs_inode_t *ip = NULL; |
@@ -1176,6 +1173,13 @@ xfs_sync_inodes( | |||
1176 | } | 1173 | } |
1177 | 1174 | ||
1178 | } | 1175 | } |
1176 | /* | ||
1177 | * When freezing, we need to wait ensure all I/O (including direct | ||
1178 | * I/O) is complete to ensure no further data modification can take | ||
1179 | * place after this point | ||
1180 | */ | ||
1181 | if (flags & SYNC_IOWAIT) | ||
1182 | vn_iowait(vp); | ||
1179 | 1183 | ||
1180 | if (flags & SYNC_BDFLUSH) { | 1184 | if (flags & SYNC_BDFLUSH) { |
1181 | if ((flags & SYNC_ATTR) && | 1185 | if ((flags & SYNC_ATTR) && |
@@ -1412,17 +1416,13 @@ xfs_sync_inodes( | |||
1412 | * xfs sync routine for internal use | 1416 | * xfs sync routine for internal use |
1413 | * | 1417 | * |
1414 | * This routine supports all of the flags defined for the generic vfs_sync | 1418 | * This routine supports all of the flags defined for the generic vfs_sync |
1415 | * interface as explained above under xfs_sync. In the interests of not | 1419 | * interface as explained above under xfs_sync. |
1416 | * changing interfaces within the 6.5 family, additional internally- | ||
1417 | * required functions are specified within a separate xflags parameter, | ||
1418 | * only available by calling this routine. | ||
1419 | * | 1420 | * |
1420 | */ | 1421 | */ |
1421 | int | 1422 | int |
1422 | xfs_syncsub( | 1423 | xfs_syncsub( |
1423 | xfs_mount_t *mp, | 1424 | xfs_mount_t *mp, |
1424 | int flags, | 1425 | int flags, |
1425 | int xflags, | ||
1426 | int *bypassed) | 1426 | int *bypassed) |
1427 | { | 1427 | { |
1428 | int error = 0; | 1428 | int error = 0; |
@@ -1444,7 +1444,7 @@ xfs_syncsub( | |||
1444 | if (flags & SYNC_BDFLUSH) | 1444 | if (flags & SYNC_BDFLUSH) |
1445 | xfs_finish_reclaim_all(mp, 1); | 1445 | xfs_finish_reclaim_all(mp, 1); |
1446 | else | 1446 | else |
1447 | error = xfs_sync_inodes(mp, flags, xflags, bypassed); | 1447 | error = xfs_sync_inodes(mp, flags, bypassed); |
1448 | } | 1448 | } |
1449 | 1449 | ||
1450 | /* | 1450 | /* |
@@ -1958,15 +1958,26 @@ xfs_showargs( | |||
1958 | return 0; | 1958 | return 0; |
1959 | } | 1959 | } |
1960 | 1960 | ||
1961 | /* | ||
1962 | * Second stage of a freeze. The data is already frozen, now we have to take | ||
1963 | * care of the metadata. New transactions are already blocked, so we need to | ||
1964 | * wait for any remaining transactions to drain out before proceding. | ||
1965 | */ | ||
1961 | STATIC void | 1966 | STATIC void |
1962 | xfs_freeze( | 1967 | xfs_freeze( |
1963 | bhv_desc_t *bdp) | 1968 | bhv_desc_t *bdp) |
1964 | { | 1969 | { |
1965 | xfs_mount_t *mp = XFS_BHVTOM(bdp); | 1970 | xfs_mount_t *mp = XFS_BHVTOM(bdp); |
1966 | 1971 | ||
1972 | /* wait for all modifications to complete */ | ||
1967 | while (atomic_read(&mp->m_active_trans) > 0) | 1973 | while (atomic_read(&mp->m_active_trans) > 0) |
1968 | delay(100); | 1974 | delay(100); |
1969 | 1975 | ||
1976 | /* flush inodes and push all remaining buffers out to disk */ | ||
1977 | xfs_quiesce_fs(mp); | ||
1978 | |||
1979 | ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0); | ||
1980 | |||
1970 | /* Push the superblock and write an unmount record */ | 1981 | /* Push the superblock and write an unmount record */ |
1971 | xfs_log_unmount_write(mp); | 1982 | xfs_log_unmount_write(mp); |
1972 | xfs_unmountfs_writesb(mp); | 1983 | xfs_unmountfs_writesb(mp); |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index bda774a04b8f..52c41714ec54 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include "xfs_refcache.h" | 51 | #include "xfs_refcache.h" |
52 | #include "xfs_trans_space.h" | 52 | #include "xfs_trans_space.h" |
53 | #include "xfs_log_priv.h" | 53 | #include "xfs_log_priv.h" |
54 | #include "xfs_mac.h" | ||
55 | 54 | ||
56 | STATIC int | 55 | STATIC int |
57 | xfs_open( | 56 | xfs_open( |
@@ -1381,7 +1380,7 @@ xfs_inactive_symlink_rmt( | |||
1381 | /* | 1380 | /* |
1382 | * Commit the first transaction. This logs the EFI and the inode. | 1381 | * Commit the first transaction. This logs the EFI and the inode. |
1383 | */ | 1382 | */ |
1384 | if ((error = xfs_bmap_finish(&tp, &free_list, first_block, &committed))) | 1383 | if ((error = xfs_bmap_finish(&tp, &free_list, &committed))) |
1385 | goto error1; | 1384 | goto error1; |
1386 | /* | 1385 | /* |
1387 | * The transaction must have been committed, since there were | 1386 | * The transaction must have been committed, since there were |
@@ -1790,8 +1789,7 @@ xfs_inactive( | |||
1790 | * Just ignore errors at this point. There is | 1789 | * Just ignore errors at this point. There is |
1791 | * nothing we can do except to try to keep going. | 1790 | * nothing we can do except to try to keep going. |
1792 | */ | 1791 | */ |
1793 | (void) xfs_bmap_finish(&tp, &free_list, first_block, | 1792 | (void) xfs_bmap_finish(&tp, &free_list, &committed); |
1794 | &committed); | ||
1795 | (void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); | 1793 | (void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); |
1796 | } | 1794 | } |
1797 | /* | 1795 | /* |
@@ -2022,7 +2020,7 @@ xfs_create( | |||
2022 | IHOLD(ip); | 2020 | IHOLD(ip); |
2023 | vp = XFS_ITOV(ip); | 2021 | vp = XFS_ITOV(ip); |
2024 | 2022 | ||
2025 | error = xfs_bmap_finish(&tp, &free_list, first_block, &committed); | 2023 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
2026 | if (error) { | 2024 | if (error) { |
2027 | xfs_bmap_cancel(&free_list); | 2025 | xfs_bmap_cancel(&free_list); |
2028 | goto abort_rele; | 2026 | goto abort_rele; |
@@ -2507,7 +2505,7 @@ xfs_remove( | |||
2507 | xfs_trans_set_sync(tp); | 2505 | xfs_trans_set_sync(tp); |
2508 | } | 2506 | } |
2509 | 2507 | ||
2510 | error = xfs_bmap_finish(&tp, &free_list, first_block, &committed); | 2508 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
2511 | if (error) { | 2509 | if (error) { |
2512 | REMOVE_DEBUG_TRACE(__LINE__); | 2510 | REMOVE_DEBUG_TRACE(__LINE__); |
2513 | goto error_rele; | 2511 | goto error_rele; |
@@ -2715,7 +2713,7 @@ xfs_link( | |||
2715 | xfs_trans_set_sync(tp); | 2713 | xfs_trans_set_sync(tp); |
2716 | } | 2714 | } |
2717 | 2715 | ||
2718 | error = xfs_bmap_finish (&tp, &free_list, first_block, &committed); | 2716 | error = xfs_bmap_finish (&tp, &free_list, &committed); |
2719 | if (error) { | 2717 | if (error) { |
2720 | xfs_bmap_cancel(&free_list); | 2718 | xfs_bmap_cancel(&free_list); |
2721 | goto abort_return; | 2719 | goto abort_return; |
@@ -2932,7 +2930,7 @@ xfs_mkdir( | |||
2932 | xfs_trans_set_sync(tp); | 2930 | xfs_trans_set_sync(tp); |
2933 | } | 2931 | } |
2934 | 2932 | ||
2935 | error = xfs_bmap_finish(&tp, &free_list, first_block, &committed); | 2933 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
2936 | if (error) { | 2934 | if (error) { |
2937 | IRELE(cdp); | 2935 | IRELE(cdp); |
2938 | goto error2; | 2936 | goto error2; |
@@ -3183,7 +3181,7 @@ xfs_rmdir( | |||
3183 | xfs_trans_set_sync(tp); | 3181 | xfs_trans_set_sync(tp); |
3184 | } | 3182 | } |
3185 | 3183 | ||
3186 | error = xfs_bmap_finish (&tp, &free_list, first_block, &committed); | 3184 | error = xfs_bmap_finish (&tp, &free_list, &committed); |
3187 | if (error) { | 3185 | if (error) { |
3188 | xfs_bmap_cancel(&free_list); | 3186 | xfs_bmap_cancel(&free_list); |
3189 | xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | | 3187 | xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | |
@@ -3533,7 +3531,7 @@ xfs_symlink( | |||
3533 | */ | 3531 | */ |
3534 | IHOLD(ip); | 3532 | IHOLD(ip); |
3535 | 3533 | ||
3536 | error = xfs_bmap_finish(&tp, &free_list, first_block, &committed); | 3534 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
3537 | if (error) { | 3535 | if (error) { |
3538 | goto error2; | 3536 | goto error2; |
3539 | } | 3537 | } |
@@ -4145,7 +4143,7 @@ retry: | |||
4145 | /* | 4143 | /* |
4146 | * Complete the transaction | 4144 | * Complete the transaction |
4147 | */ | 4145 | */ |
4148 | error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); | 4146 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
4149 | if (error) { | 4147 | if (error) { |
4150 | goto error0; | 4148 | goto error0; |
4151 | } | 4149 | } |
@@ -4452,7 +4450,7 @@ xfs_free_file_space( | |||
4452 | /* | 4450 | /* |
4453 | * complete the transaction | 4451 | * complete the transaction |
4454 | */ | 4452 | */ |
4455 | error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); | 4453 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
4456 | if (error) { | 4454 | if (error) { |
4457 | goto error0; | 4455 | goto error0; |
4458 | } | 4456 | } |