diff options
author | David S. Miller <davem@davemloft.net> | 2008-04-03 17:33:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-03 17:33:42 -0400 |
commit | 3bb5da3837cc1aa17736b05139c9a22c3794851a (patch) | |
tree | c92d5684a866542b1cb20641607ac1643ce03a47 /fs | |
parent | 7feb49c82a74bc7c091b8ab2a3f96baa33d08ece (diff) | |
parent | 9597362d354f8655ece324b01d0c640a0e99c077 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'fs')
55 files changed, 687 insertions, 718 deletions
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 970d38f30565..584bb0f9c36a 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -127,14 +127,21 @@ struct afs_cell *afs_cell_create(const char *name, char *vllist) | |||
127 | 127 | ||
128 | _enter("%s,%s", name, vllist); | 128 | _enter("%s,%s", name, vllist); |
129 | 129 | ||
130 | down_write(&afs_cells_sem); | ||
131 | read_lock(&afs_cells_lock); | ||
132 | list_for_each_entry(cell, &afs_cells, link) { | ||
133 | if (strcasecmp(cell->name, name) == 0) | ||
134 | goto duplicate_name; | ||
135 | } | ||
136 | read_unlock(&afs_cells_lock); | ||
137 | |||
130 | cell = afs_cell_alloc(name, vllist); | 138 | cell = afs_cell_alloc(name, vllist); |
131 | if (IS_ERR(cell)) { | 139 | if (IS_ERR(cell)) { |
132 | _leave(" = %ld", PTR_ERR(cell)); | 140 | _leave(" = %ld", PTR_ERR(cell)); |
141 | up_write(&afs_cells_sem); | ||
133 | return cell; | 142 | return cell; |
134 | } | 143 | } |
135 | 144 | ||
136 | down_write(&afs_cells_sem); | ||
137 | |||
138 | /* add a proc directory for this cell */ | 145 | /* add a proc directory for this cell */ |
139 | ret = afs_proc_cell_setup(cell); | 146 | ret = afs_proc_cell_setup(cell); |
140 | if (ret < 0) | 147 | if (ret < 0) |
@@ -167,6 +174,11 @@ error: | |||
167 | kfree(cell); | 174 | kfree(cell); |
168 | _leave(" = %d", ret); | 175 | _leave(" = %d", ret); |
169 | return ERR_PTR(ret); | 176 | return ERR_PTR(ret); |
177 | |||
178 | duplicate_name: | ||
179 | read_unlock(&afs_cells_lock); | ||
180 | up_write(&afs_cells_sem); | ||
181 | return ERR_PTR(-EEXIST); | ||
170 | } | 182 | } |
171 | 183 | ||
172 | /* | 184 | /* |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 5ca3625cd39e..9ba16edc0af2 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -573,7 +573,6 @@ extern const struct file_operations afs_mntpt_file_operations; | |||
573 | 573 | ||
574 | extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); | 574 | extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); |
575 | extern void afs_mntpt_kill_timer(void); | 575 | extern void afs_mntpt_kill_timer(void); |
576 | extern void afs_umount_begin(struct vfsmount *, int); | ||
577 | 576 | ||
578 | /* | 577 | /* |
579 | * proc.c | 578 | * proc.c |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index a3510b8ba3e7..2f5503902c37 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -283,11 +283,3 @@ void afs_mntpt_kill_timer(void) | |||
283 | cancel_delayed_work(&afs_mntpt_expiry_timer); | 283 | cancel_delayed_work(&afs_mntpt_expiry_timer); |
284 | flush_scheduled_work(); | 284 | flush_scheduled_work(); |
285 | } | 285 | } |
286 | |||
287 | /* | ||
288 | * begin unmount by attempting to remove all automounted mountpoints we added | ||
289 | */ | ||
290 | void afs_umount_begin(struct vfsmount *vfsmnt, int flags) | ||
291 | { | ||
292 | shrink_submounts(vfsmnt, &afs_vfsmounts); | ||
293 | } | ||
diff --git a/fs/afs/super.c b/fs/afs/super.c index 36bbce45f44b..4b572b801d8d 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -50,7 +50,6 @@ static const struct super_operations afs_super_ops = { | |||
50 | .write_inode = afs_write_inode, | 50 | .write_inode = afs_write_inode, |
51 | .destroy_inode = afs_destroy_inode, | 51 | .destroy_inode = afs_destroy_inode, |
52 | .clear_inode = afs_clear_inode, | 52 | .clear_inode = afs_clear_inode, |
53 | .umount_begin = afs_umount_begin, | ||
54 | .put_super = afs_put_super, | 53 | .put_super = afs_put_super, |
55 | .show_options = generic_show_options, | 54 | .show_options = generic_show_options, |
56 | }; | 55 | }; |
@@ -996,6 +996,14 @@ put_rq: | |||
996 | /* everything turned out well, dispose of the aiocb. */ | 996 | /* everything turned out well, dispose of the aiocb. */ |
997 | ret = __aio_put_req(ctx, iocb); | 997 | ret = __aio_put_req(ctx, iocb); |
998 | 998 | ||
999 | /* | ||
1000 | * We have to order our ring_info tail store above and test | ||
1001 | * of the wait list below outside the wait lock. This is | ||
1002 | * like in wake_up_bit() where clearing a bit has to be | ||
1003 | * ordered with the unlocked test. | ||
1004 | */ | ||
1005 | smp_mb(); | ||
1006 | |||
999 | if (waitqueue_active(&ctx->wait)) | 1007 | if (waitqueue_active(&ctx->wait)) |
1000 | wake_up(&ctx->wait); | 1008 | wake_up(&ctx->wait); |
1001 | 1009 | ||
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 23321889d9b0..f42be069e085 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c | |||
@@ -81,13 +81,10 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, | |||
81 | 81 | ||
82 | if (IS_ERR(anon_inode_inode)) | 82 | if (IS_ERR(anon_inode_inode)) |
83 | return -ENODEV; | 83 | return -ENODEV; |
84 | file = get_empty_filp(); | ||
85 | if (!file) | ||
86 | return -ENFILE; | ||
87 | 84 | ||
88 | error = get_unused_fd(); | 85 | error = get_unused_fd(); |
89 | if (error < 0) | 86 | if (error < 0) |
90 | goto err_put_filp; | 87 | return error; |
91 | fd = error; | 88 | fd = error; |
92 | 89 | ||
93 | /* | 90 | /* |
@@ -114,14 +111,15 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, | |||
114 | dentry->d_flags &= ~DCACHE_UNHASHED; | 111 | dentry->d_flags &= ~DCACHE_UNHASHED; |
115 | d_instantiate(dentry, anon_inode_inode); | 112 | d_instantiate(dentry, anon_inode_inode); |
116 | 113 | ||
117 | file->f_path.mnt = mntget(anon_inode_mnt); | 114 | error = -ENFILE; |
118 | file->f_path.dentry = dentry; | 115 | file = alloc_file(anon_inode_mnt, dentry, |
116 | FMODE_READ | FMODE_WRITE, fops); | ||
117 | if (!file) | ||
118 | goto err_dput; | ||
119 | file->f_mapping = anon_inode_inode->i_mapping; | 119 | file->f_mapping = anon_inode_inode->i_mapping; |
120 | 120 | ||
121 | file->f_pos = 0; | 121 | file->f_pos = 0; |
122 | file->f_flags = O_RDWR; | 122 | file->f_flags = O_RDWR; |
123 | file->f_op = fops; | ||
124 | file->f_mode = FMODE_READ | FMODE_WRITE; | ||
125 | file->f_version = 0; | 123 | file->f_version = 0; |
126 | file->private_data = priv; | 124 | file->private_data = priv; |
127 | 125 | ||
@@ -132,10 +130,10 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, | |||
132 | *pfile = file; | 130 | *pfile = file; |
133 | return 0; | 131 | return 0; |
134 | 132 | ||
133 | err_dput: | ||
134 | dput(dentry); | ||
135 | err_put_unused_fd: | 135 | err_put_unused_fd: |
136 | put_unused_fd(fd); | 136 | put_unused_fd(fd); |
137 | err_put_filp: | ||
138 | put_filp(file); | ||
139 | return error; | 137 | return error; |
140 | } | 138 | } |
141 | EXPORT_SYMBOL_GPL(anon_inode_getfd); | 139 | EXPORT_SYMBOL_GPL(anon_inode_getfd); |
@@ -1194,6 +1194,8 @@ EXPORT_SYMBOL(bio_hw_segments); | |||
1194 | EXPORT_SYMBOL(bio_add_page); | 1194 | EXPORT_SYMBOL(bio_add_page); |
1195 | EXPORT_SYMBOL(bio_add_pc_page); | 1195 | EXPORT_SYMBOL(bio_add_pc_page); |
1196 | EXPORT_SYMBOL(bio_get_nr_vecs); | 1196 | EXPORT_SYMBOL(bio_get_nr_vecs); |
1197 | EXPORT_SYMBOL(bio_map_user); | ||
1198 | EXPORT_SYMBOL(bio_unmap_user); | ||
1197 | EXPORT_SYMBOL(bio_map_kern); | 1199 | EXPORT_SYMBOL(bio_map_kern); |
1198 | EXPORT_SYMBOL(bio_pair_release); | 1200 | EXPORT_SYMBOL(bio_pair_release); |
1199 | EXPORT_SYMBOL(bio_split); | 1201 | EXPORT_SYMBOL(bio_split); |
diff --git a/fs/buffer.c b/fs/buffer.c index ddfdd2c80bf9..98196327ddf0 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -2564,14 +2564,13 @@ int nobh_write_end(struct file *file, struct address_space *mapping, | |||
2564 | struct inode *inode = page->mapping->host; | 2564 | struct inode *inode = page->mapping->host; |
2565 | struct buffer_head *head = fsdata; | 2565 | struct buffer_head *head = fsdata; |
2566 | struct buffer_head *bh; | 2566 | struct buffer_head *bh; |
2567 | BUG_ON(fsdata != NULL && page_has_buffers(page)); | ||
2567 | 2568 | ||
2568 | if (!PageMappedToDisk(page)) { | 2569 | if (unlikely(copied < len) && !page_has_buffers(page)) |
2569 | if (unlikely(copied < len) && !page_has_buffers(page)) | 2570 | attach_nobh_buffers(page, head); |
2570 | attach_nobh_buffers(page, head); | 2571 | if (page_has_buffers(page)) |
2571 | if (page_has_buffers(page)) | 2572 | return generic_write_end(file, mapping, pos, len, |
2572 | return generic_write_end(file, mapping, pos, len, | 2573 | copied, page, fsdata); |
2573 | copied, page, fsdata); | ||
2574 | } | ||
2575 | 2574 | ||
2576 | SetPageUptodate(page); | 2575 | SetPageUptodate(page); |
2577 | set_page_dirty(page); | 2576 | set_page_dirty(page); |
@@ -3213,7 +3212,7 @@ static int buffer_cpu_notify(struct notifier_block *self, | |||
3213 | } | 3212 | } |
3214 | 3213 | ||
3215 | /** | 3214 | /** |
3216 | * bh_uptodate_or_lock: Test whether the buffer is uptodate | 3215 | * bh_uptodate_or_lock - Test whether the buffer is uptodate |
3217 | * @bh: struct buffer_head | 3216 | * @bh: struct buffer_head |
3218 | * | 3217 | * |
3219 | * Return true if the buffer is up-to-date and false, | 3218 | * Return true if the buffer is up-to-date and false, |
@@ -3232,7 +3231,7 @@ int bh_uptodate_or_lock(struct buffer_head *bh) | |||
3232 | EXPORT_SYMBOL(bh_uptodate_or_lock); | 3231 | EXPORT_SYMBOL(bh_uptodate_or_lock); |
3233 | 3232 | ||
3234 | /** | 3233 | /** |
3235 | * bh_submit_read: Submit a locked buffer for reading | 3234 | * bh_submit_read - Submit a locked buffer for reading |
3236 | * @bh: struct buffer_head | 3235 | * @bh: struct buffer_head |
3237 | * | 3236 | * |
3238 | * Returns zero on success and -EIO on error. | 3237 | * Returns zero on success and -EIO on error. |
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 7f8838253410..56c924033b78 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
@@ -33,7 +33,6 @@ void dfs_shrink_umount_helper(struct vfsmount *vfsmnt) | |||
33 | { | 33 | { |
34 | mark_mounts_for_expiry(&cifs_dfs_automount_list); | 34 | mark_mounts_for_expiry(&cifs_dfs_automount_list); |
35 | mark_mounts_for_expiry(&cifs_dfs_automount_list); | 35 | mark_mounts_for_expiry(&cifs_dfs_automount_list); |
36 | shrink_submounts(vfsmnt, &cifs_dfs_automount_list); | ||
37 | } | 36 | } |
38 | 37 | ||
39 | /** | 38 | /** |
@@ -74,7 +73,7 @@ static char *cifs_get_share_name(const char *node_name) | |||
74 | pSep = memchr(UNC+2, '\\', len-2); | 73 | pSep = memchr(UNC+2, '\\', len-2); |
75 | if (!pSep) { | 74 | if (!pSep) { |
76 | cERROR(1, ("%s: no server name end in node name: %s", | 75 | cERROR(1, ("%s: no server name end in node name: %s", |
77 | __FUNCTION__, node_name)); | 76 | __func__, node_name)); |
78 | kfree(UNC); | 77 | kfree(UNC); |
79 | return NULL; | 78 | return NULL; |
80 | } | 79 | } |
@@ -84,7 +83,7 @@ static char *cifs_get_share_name(const char *node_name) | |||
84 | pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); | 83 | pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); |
85 | if (!pSep) { | 84 | if (!pSep) { |
86 | cERROR(1, ("%s:2 cant find share name in node name: %s", | 85 | cERROR(1, ("%s:2 cant find share name in node name: %s", |
87 | __FUNCTION__, node_name)); | 86 | __func__, node_name)); |
88 | kfree(UNC); | 87 | kfree(UNC); |
89 | return NULL; | 88 | return NULL; |
90 | } | 89 | } |
@@ -127,7 +126,7 @@ static char *compose_mount_options(const char *sb_mountdata, | |||
127 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); | 126 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); |
128 | if (rc != 0) { | 127 | if (rc != 0) { |
129 | cERROR(1, ("%s: Failed to resolve server part of %s to IP", | 128 | cERROR(1, ("%s: Failed to resolve server part of %s to IP", |
130 | __FUNCTION__, *devname)); | 129 | __func__, *devname)); |
131 | mountdata = ERR_PTR(rc); | 130 | mountdata = ERR_PTR(rc); |
132 | goto compose_mount_options_out; | 131 | goto compose_mount_options_out; |
133 | } | 132 | } |
@@ -181,8 +180,8 @@ static char *compose_mount_options(const char *sb_mountdata, | |||
181 | } | 180 | } |
182 | } | 181 | } |
183 | 182 | ||
184 | /*cFYI(1,("%s: parent mountdata: %s", __FUNCTION__,sb_mountdata));*/ | 183 | /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/ |
185 | /*cFYI(1, ("%s: submount mountdata: %s", __FUNCTION__, mountdata ));*/ | 184 | /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/ |
186 | 185 | ||
187 | compose_mount_options_out: | 186 | compose_mount_options_out: |
188 | kfree(srvIP); | 187 | kfree(srvIP); |
@@ -302,7 +301,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
302 | int rc = 0; | 301 | int rc = 0; |
303 | struct vfsmount *mnt = ERR_PTR(-ENOENT); | 302 | struct vfsmount *mnt = ERR_PTR(-ENOENT); |
304 | 303 | ||
305 | cFYI(1, ("in %s", __FUNCTION__)); | 304 | cFYI(1, ("in %s", __func__)); |
306 | BUG_ON(IS_ROOT(dentry)); | 305 | BUG_ON(IS_ROOT(dentry)); |
307 | 306 | ||
308 | xid = GetXid(); | 307 | xid = GetXid(); |
@@ -336,7 +335,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
336 | len = strlen(referrals[i].node_name); | 335 | len = strlen(referrals[i].node_name); |
337 | if (len < 2) { | 336 | if (len < 2) { |
338 | cERROR(1, ("%s: Net Address path too short: %s", | 337 | cERROR(1, ("%s: Net Address path too short: %s", |
339 | __FUNCTION__, referrals[i].node_name)); | 338 | __func__, referrals[i].node_name)); |
340 | rc = -EINVAL; | 339 | rc = -EINVAL; |
341 | goto out_err; | 340 | goto out_err; |
342 | } | 341 | } |
@@ -344,7 +343,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
344 | nd->path.dentry, | 343 | nd->path.dentry, |
345 | referrals[i].node_name); | 344 | referrals[i].node_name); |
346 | cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", | 345 | cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", |
347 | __FUNCTION__, | 346 | __func__, |
348 | referrals[i].node_name, mnt)); | 347 | referrals[i].node_name, mnt)); |
349 | 348 | ||
350 | /* complete mount procedure if we accured submount */ | 349 | /* complete mount procedure if we accured submount */ |
@@ -365,7 +364,7 @@ out: | |||
365 | FreeXid(xid); | 364 | FreeXid(xid); |
366 | free_dfs_info_array(referrals, num_referrals); | 365 | free_dfs_info_array(referrals, num_referrals); |
367 | kfree(full_path); | 366 | kfree(full_path); |
368 | cFYI(1, ("leaving %s" , __FUNCTION__)); | 367 | cFYI(1, ("leaving %s" , __func__)); |
369 | return ERR_PTR(rc); | 368 | return ERR_PTR(rc); |
370 | out_err: | 369 | out_err: |
371 | path_put(&nd->path); | 370 | path_put(&nd->path); |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index f93932c21772..1cb5b0a9f2ac 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/cifsacl.c | 2 | * fs/cifs/cifsacl.c |
3 | * | 3 | * |
4 | * Copyright (C) International Business Machines Corp., 2007 | 4 | * Copyright (C) International Business Machines Corp., 2007,2008 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * Contains the routines for mapping CIFS/NTFS ACLs | 7 | * Contains the routines for mapping CIFS/NTFS ACLs |
@@ -261,7 +261,7 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use, | |||
261 | return; | 261 | return; |
262 | } | 262 | } |
263 | 263 | ||
264 | static __le16 fill_ace_for_sid(struct cifs_ace *pntace, | 264 | static __u16 fill_ace_for_sid(struct cifs_ace *pntace, |
265 | const struct cifs_sid *psid, __u64 nmode, umode_t bits) | 265 | const struct cifs_sid *psid, __u64 nmode, umode_t bits) |
266 | { | 266 | { |
267 | int i; | 267 | int i; |
@@ -411,7 +411,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
411 | static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, | 411 | static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, |
412 | struct cifs_sid *pgrpsid, __u64 nmode) | 412 | struct cifs_sid *pgrpsid, __u64 nmode) |
413 | { | 413 | { |
414 | __le16 size = 0; | 414 | u16 size = 0; |
415 | struct cifs_acl *pnndacl; | 415 | struct cifs_acl *pnndacl; |
416 | 416 | ||
417 | pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl)); | 417 | pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl)); |
@@ -556,9 +556,9 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, | |||
556 | 556 | ||
557 | /* Retrieve an ACL from the server */ | 557 | /* Retrieve an ACL from the server */ |
558 | static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, | 558 | static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, |
559 | const char *path) | 559 | const char *path, const __u16 *pfid) |
560 | { | 560 | { |
561 | struct cifsFileInfo *open_file; | 561 | struct cifsFileInfo *open_file = NULL; |
562 | int unlock_file = FALSE; | 562 | int unlock_file = FALSE; |
563 | int xid; | 563 | int xid; |
564 | int rc = -EIO; | 564 | int rc = -EIO; |
@@ -573,7 +573,11 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, | |||
573 | return NULL; | 573 | return NULL; |
574 | 574 | ||
575 | xid = GetXid(); | 575 | xid = GetXid(); |
576 | open_file = find_readable_file(CIFS_I(inode)); | 576 | if (pfid == NULL) |
577 | open_file = find_readable_file(CIFS_I(inode)); | ||
578 | else | ||
579 | fid = *pfid; | ||
580 | |||
577 | sb = inode->i_sb; | 581 | sb = inode->i_sb; |
578 | if (sb == NULL) { | 582 | if (sb == NULL) { |
579 | FreeXid(xid); | 583 | FreeXid(xid); |
@@ -584,7 +588,7 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, | |||
584 | if (open_file) { | 588 | if (open_file) { |
585 | unlock_file = TRUE; | 589 | unlock_file = TRUE; |
586 | fid = open_file->netfid; | 590 | fid = open_file->netfid; |
587 | } else { | 591 | } else if (pfid == NULL) { |
588 | int oplock = FALSE; | 592 | int oplock = FALSE; |
589 | /* open file */ | 593 | /* open file */ |
590 | rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, | 594 | rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, |
@@ -600,10 +604,11 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, | |||
600 | 604 | ||
601 | rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); | 605 | rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); |
602 | cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); | 606 | cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); |
603 | if (unlock_file == TRUE) | 607 | if (unlock_file == TRUE) /* find_readable_file increments ref count */ |
604 | atomic_dec(&open_file->wrtPending); | 608 | atomic_dec(&open_file->wrtPending); |
605 | else | 609 | else if (pfid == NULL) /* if opened above we have to close the handle */ |
606 | CIFSSMBClose(xid, cifs_sb->tcon, fid); | 610 | CIFSSMBClose(xid, cifs_sb->tcon, fid); |
611 | /* else handle was passed in by caller */ | ||
607 | 612 | ||
608 | FreeXid(xid); | 613 | FreeXid(xid); |
609 | return pntsd; | 614 | return pntsd; |
@@ -664,14 +669,14 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
664 | } | 669 | } |
665 | 670 | ||
666 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 671 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ |
667 | void acl_to_uid_mode(struct inode *inode, const char *path) | 672 | void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid) |
668 | { | 673 | { |
669 | struct cifs_ntsd *pntsd = NULL; | 674 | struct cifs_ntsd *pntsd = NULL; |
670 | u32 acllen = 0; | 675 | u32 acllen = 0; |
671 | int rc = 0; | 676 | int rc = 0; |
672 | 677 | ||
673 | cFYI(DBG2, ("converting ACL to mode for %s", path)); | 678 | cFYI(DBG2, ("converting ACL to mode for %s", path)); |
674 | pntsd = get_cifs_acl(&acllen, inode, path); | 679 | pntsd = get_cifs_acl(&acllen, inode, path, pfid); |
675 | 680 | ||
676 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | 681 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ |
677 | if (pntsd) | 682 | if (pntsd) |
@@ -694,7 +699,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) | |||
694 | cFYI(DBG2, ("set ACL from mode for %s", path)); | 699 | cFYI(DBG2, ("set ACL from mode for %s", path)); |
695 | 700 | ||
696 | /* Get the security descriptor */ | 701 | /* Get the security descriptor */ |
697 | pntsd = get_cifs_acl(&acllen, inode, path); | 702 | pntsd = get_cifs_acl(&acllen, inode, path, NULL); |
698 | 703 | ||
699 | /* Add three ACEs for owner, group, everyone getting rid of | 704 | /* Add three ACEs for owner, group, everyone getting rid of |
700 | other ACEs as chmod disables ACEs and set the security descriptor */ | 705 | other ACEs as chmod disables ACEs and set the security descriptor */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0af63e6b426b..7e5e0e78cd72 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -39,8 +39,8 @@ extern int smb_send(struct socket *, struct smb_hdr *, | |||
39 | unsigned int /* length */ , struct sockaddr *); | 39 | unsigned int /* length */ , struct sockaddr *); |
40 | extern unsigned int _GetXid(void); | 40 | extern unsigned int _GetXid(void); |
41 | extern void _FreeXid(unsigned int); | 41 | extern void _FreeXid(unsigned int); |
42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid)); | 42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid)); |
43 | #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));} | 43 | #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} |
44 | extern char *build_path_from_dentry(struct dentry *); | 44 | extern char *build_path_from_dentry(struct dentry *); |
45 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); | 45 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); |
46 | /* extern void renew_parental_timestamps(struct dentry *direntry);*/ | 46 | /* extern void renew_parental_timestamps(struct dentry *direntry);*/ |
@@ -92,11 +92,12 @@ extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); | |||
92 | extern int cifs_get_inode_info(struct inode **pinode, | 92 | extern int cifs_get_inode_info(struct inode **pinode, |
93 | const unsigned char *search_path, | 93 | const unsigned char *search_path, |
94 | FILE_ALL_INFO * pfile_info, | 94 | FILE_ALL_INFO * pfile_info, |
95 | struct super_block *sb, int xid); | 95 | struct super_block *sb, int xid, const __u16 *pfid); |
96 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 96 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
97 | const unsigned char *search_path, | 97 | const unsigned char *search_path, |
98 | struct super_block *sb, int xid); | 98 | struct super_block *sb, int xid); |
99 | extern void acl_to_uid_mode(struct inode *inode, const char *search_path); | 99 | extern void acl_to_uid_mode(struct inode *inode, const char *path, |
100 | const __u16 *pfid); | ||
100 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); | 101 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); |
101 | 102 | ||
102 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 103 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 4e83b47c4b34..0f5c62ba4038 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -229,7 +229,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
229 | inode->i_sb, xid); | 229 | inode->i_sb, xid); |
230 | else { | 230 | else { |
231 | rc = cifs_get_inode_info(&newinode, full_path, | 231 | rc = cifs_get_inode_info(&newinode, full_path, |
232 | buf, inode->i_sb, xid); | 232 | buf, inode->i_sb, xid, |
233 | &fileHandle); | ||
233 | if (newinode) { | 234 | if (newinode) { |
234 | newinode->i_mode = mode; | 235 | newinode->i_mode = mode; |
235 | if ((oplock & CIFS_CREATE_ACTION) && | 236 | if ((oplock & CIFS_CREATE_ACTION) && |
@@ -483,7 +484,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
483 | parent_dir_inode->i_sb, xid); | 484 | parent_dir_inode->i_sb, xid); |
484 | else | 485 | else |
485 | rc = cifs_get_inode_info(&newInode, full_path, NULL, | 486 | rc = cifs_get_inode_info(&newInode, full_path, NULL, |
486 | parent_dir_inode->i_sb, xid); | 487 | parent_dir_inode->i_sb, xid, NULL); |
487 | 488 | ||
488 | if ((rc == 0) && (newInode != NULL)) { | 489 | if ((rc == 0) && (newInode != NULL)) { |
489 | if (pTcon->nocase) | 490 | if (pTcon->nocase) |
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index ef7f43824347..7cc86c418182 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c | |||
@@ -77,14 +77,14 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
77 | /* search for server name delimiter */ | 77 | /* search for server name delimiter */ |
78 | len = strlen(unc); | 78 | len = strlen(unc); |
79 | if (len < 3) { | 79 | if (len < 3) { |
80 | cFYI(1, ("%s: unc is too short: %s", __FUNCTION__, unc)); | 80 | cFYI(1, ("%s: unc is too short: %s", __func__, unc)); |
81 | return -EINVAL; | 81 | return -EINVAL; |
82 | } | 82 | } |
83 | len -= 2; | 83 | len -= 2; |
84 | name = memchr(unc+2, '\\', len); | 84 | name = memchr(unc+2, '\\', len); |
85 | if (!name) { | 85 | if (!name) { |
86 | cFYI(1, ("%s: probably server name is whole unc: %s", | 86 | cFYI(1, ("%s: probably server name is whole unc: %s", |
87 | __FUNCTION__, unc)); | 87 | __func__, unc)); |
88 | } else { | 88 | } else { |
89 | len = (name - unc) - 2/* leading // */; | 89 | len = (name - unc) - 2/* leading // */; |
90 | } | 90 | } |
@@ -104,7 +104,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
104 | if (*ip_addr) { | 104 | if (*ip_addr) { |
105 | memcpy(*ip_addr, rkey->payload.data, len); | 105 | memcpy(*ip_addr, rkey->payload.data, len); |
106 | (*ip_addr)[len] = '\0'; | 106 | (*ip_addr)[len] = '\0'; |
107 | cFYI(1, ("%s: resolved: %s to %s", __FUNCTION__, | 107 | cFYI(1, ("%s: resolved: %s to %s", __func__, |
108 | rkey->description, | 108 | rkey->description, |
109 | *ip_addr | 109 | *ip_addr |
110 | )); | 110 | )); |
@@ -114,7 +114,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
114 | } | 114 | } |
115 | key_put(rkey); | 115 | key_put(rkey); |
116 | } else { | 116 | } else { |
117 | cERROR(1, ("%s: unable to resolve: %s", __FUNCTION__, name)); | 117 | cERROR(1, ("%s: unable to resolve: %s", __func__, name)); |
118 | } | 118 | } |
119 | 119 | ||
120 | kfree(name); | 120 | kfree(name); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index fa849c91d323..40b690073fc1 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -145,7 +145,7 @@ client_can_cache: | |||
145 | full_path, inode->i_sb, xid); | 145 | full_path, inode->i_sb, xid); |
146 | else | 146 | else |
147 | rc = cifs_get_inode_info(&file->f_path.dentry->d_inode, | 147 | rc = cifs_get_inode_info(&file->f_path.dentry->d_inode, |
148 | full_path, buf, inode->i_sb, xid); | 148 | full_path, buf, inode->i_sb, xid, NULL); |
149 | 149 | ||
150 | if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { | 150 | if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { |
151 | pCifsInode->clientCanCacheAll = TRUE; | 151 | pCifsInode->clientCanCacheAll = TRUE; |
@@ -440,7 +440,7 @@ reopen_error_exit: | |||
440 | else | 440 | else |
441 | rc = cifs_get_inode_info(&inode, | 441 | rc = cifs_get_inode_info(&inode, |
442 | full_path, NULL, inode->i_sb, | 442 | full_path, NULL, inode->i_sb, |
443 | xid); | 443 | xid, NULL); |
444 | } /* else we are writing out data to server already | 444 | } /* else we are writing out data to server already |
445 | and could deadlock if we tried to flush data, and | 445 | and could deadlock if we tried to flush data, and |
446 | since we do not know if we have data that would | 446 | since we do not know if we have data that would |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 24eb4d392155..bc673c8c1e6b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include "cifs_fs_sb.h" | 30 | #include "cifs_fs_sb.h" |
31 | 31 | ||
32 | 32 | ||
33 | static void cifs_set_ops(struct inode *inode) | 33 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) |
34 | { | 34 | { |
35 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 35 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
36 | 36 | ||
@@ -57,8 +57,16 @@ static void cifs_set_ops(struct inode *inode) | |||
57 | inode->i_data.a_ops = &cifs_addr_ops; | 57 | inode->i_data.a_ops = &cifs_addr_ops; |
58 | break; | 58 | break; |
59 | case S_IFDIR: | 59 | case S_IFDIR: |
60 | inode->i_op = &cifs_dir_inode_ops; | 60 | #ifdef CONFIG_CIFS_DFS_UPCALL |
61 | inode->i_fop = &cifs_dir_ops; | 61 | if (is_dfs_referral) { |
62 | inode->i_op = &cifs_dfs_referral_inode_operations; | ||
63 | } else { | ||
64 | #else /* NO DFS support, treat as a directory */ | ||
65 | { | ||
66 | #endif | ||
67 | inode->i_op = &cifs_dir_inode_ops; | ||
68 | inode->i_fop = &cifs_dir_ops; | ||
69 | } | ||
62 | break; | 70 | break; |
63 | case S_IFLNK: | 71 | case S_IFLNK: |
64 | inode->i_op = &cifs_symlink_inode_ops; | 72 | inode->i_op = &cifs_symlink_inode_ops; |
@@ -153,6 +161,30 @@ static void cifs_unix_info_to_inode(struct inode *inode, | |||
153 | spin_unlock(&inode->i_lock); | 161 | spin_unlock(&inode->i_lock); |
154 | } | 162 | } |
155 | 163 | ||
164 | static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon, | ||
165 | const char *search_path) | ||
166 | { | ||
167 | int tree_len; | ||
168 | int path_len; | ||
169 | char *tmp_path; | ||
170 | |||
171 | if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS)) | ||
172 | return search_path; | ||
173 | |||
174 | /* use full path name for working with DFS */ | ||
175 | tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1); | ||
176 | path_len = strnlen(search_path, MAX_PATHCONF); | ||
177 | |||
178 | tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL); | ||
179 | if (tmp_path == NULL) | ||
180 | return search_path; | ||
181 | |||
182 | strncpy(tmp_path, pTcon->treeName, tree_len); | ||
183 | strncpy(tmp_path+tree_len, search_path, path_len); | ||
184 | tmp_path[tree_len+path_len] = 0; | ||
185 | return tmp_path; | ||
186 | } | ||
187 | |||
156 | int cifs_get_inode_info_unix(struct inode **pinode, | 188 | int cifs_get_inode_info_unix(struct inode **pinode, |
157 | const unsigned char *search_path, struct super_block *sb, int xid) | 189 | const unsigned char *search_path, struct super_block *sb, int xid) |
158 | { | 190 | { |
@@ -161,41 +193,31 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
161 | struct cifsTconInfo *pTcon; | 193 | struct cifsTconInfo *pTcon; |
162 | struct inode *inode; | 194 | struct inode *inode; |
163 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 195 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
164 | char *tmp_path; | 196 | const unsigned char *full_path; |
197 | bool is_dfs_referral = false; | ||
165 | 198 | ||
166 | pTcon = cifs_sb->tcon; | 199 | pTcon = cifs_sb->tcon; |
167 | cFYI(1, ("Getting info on %s", search_path)); | 200 | cFYI(1, ("Getting info on %s", search_path)); |
201 | |||
202 | full_path = cifs_get_search_path(pTcon, search_path); | ||
203 | |||
204 | try_again_CIFSSMBUnixQPathInfo: | ||
168 | /* could have done a find first instead but this returns more info */ | 205 | /* could have done a find first instead but this returns more info */ |
169 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, | 206 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, |
170 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 207 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
171 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 208 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
172 | /* dump_mem("\nUnixQPathInfo return data", &findData, | 209 | /* dump_mem("\nUnixQPathInfo return data", &findData, |
173 | sizeof(findData)); */ | 210 | sizeof(findData)); */ |
174 | if (rc) { | 211 | if (rc) { |
175 | if (rc == -EREMOTE) { | 212 | if (rc == -EREMOTE && !is_dfs_referral) { |
176 | tmp_path = | 213 | is_dfs_referral = true; |
177 | kmalloc(strnlen(pTcon->treeName, | 214 | if (full_path != search_path) { |
178 | MAX_TREE_SIZE + 1) + | 215 | kfree(full_path); |
179 | strnlen(search_path, MAX_PATHCONF) + 1, | 216 | full_path = search_path; |
180 | GFP_KERNEL); | 217 | } |
181 | if (tmp_path == NULL) | 218 | goto try_again_CIFSSMBUnixQPathInfo; |
182 | return -ENOMEM; | ||
183 | |||
184 | /* have to skip first of the double backslash of | ||
185 | UNC name */ | ||
186 | strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); | ||
187 | strncat(tmp_path, search_path, MAX_PATHCONF); | ||
188 | rc = connect_to_dfs_path(xid, pTcon->ses, | ||
189 | /* treename + */ tmp_path, | ||
190 | cifs_sb->local_nls, | ||
191 | cifs_sb->mnt_cifs_flags & | ||
192 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
193 | kfree(tmp_path); | ||
194 | |||
195 | /* BB fix up inode etc. */ | ||
196 | } else if (rc) { | ||
197 | return rc; | ||
198 | } | 219 | } |
220 | goto cgiiu_exit; | ||
199 | } else { | 221 | } else { |
200 | struct cifsInodeInfo *cifsInfo; | 222 | struct cifsInodeInfo *cifsInfo; |
201 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); | 223 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); |
@@ -204,8 +226,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
204 | /* get new inode */ | 226 | /* get new inode */ |
205 | if (*pinode == NULL) { | 227 | if (*pinode == NULL) { |
206 | *pinode = new_inode(sb); | 228 | *pinode = new_inode(sb); |
207 | if (*pinode == NULL) | 229 | if (*pinode == NULL) { |
208 | return -ENOMEM; | 230 | rc = -ENOMEM; |
231 | goto cgiiu_exit; | ||
232 | } | ||
209 | /* Is an i_ino of zero legal? */ | 233 | /* Is an i_ino of zero legal? */ |
210 | /* Are there sanity checks we can use to ensure that | 234 | /* Are there sanity checks we can use to ensure that |
211 | the server is really filling in that field? */ | 235 | the server is really filling in that field? */ |
@@ -237,8 +261,11 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
237 | (unsigned long) inode->i_size, | 261 | (unsigned long) inode->i_size, |
238 | (unsigned long long)inode->i_blocks)); | 262 | (unsigned long long)inode->i_blocks)); |
239 | 263 | ||
240 | cifs_set_ops(inode); | 264 | cifs_set_ops(inode, is_dfs_referral); |
241 | } | 265 | } |
266 | cgiiu_exit: | ||
267 | if (full_path != search_path) | ||
268 | kfree(full_path); | ||
242 | return rc; | 269 | return rc; |
243 | } | 270 | } |
244 | 271 | ||
@@ -347,15 +374,16 @@ static int get_sfu_mode(struct inode *inode, | |||
347 | 374 | ||
348 | int cifs_get_inode_info(struct inode **pinode, | 375 | int cifs_get_inode_info(struct inode **pinode, |
349 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, | 376 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, |
350 | struct super_block *sb, int xid) | 377 | struct super_block *sb, int xid, const __u16 *pfid) |
351 | { | 378 | { |
352 | int rc = 0; | 379 | int rc = 0; |
353 | struct cifsTconInfo *pTcon; | 380 | struct cifsTconInfo *pTcon; |
354 | struct inode *inode; | 381 | struct inode *inode; |
355 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 382 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
356 | char *tmp_path; | 383 | const unsigned char *full_path = NULL; |
357 | char *buf = NULL; | 384 | char *buf = NULL; |
358 | int adjustTZ = FALSE; | 385 | int adjustTZ = FALSE; |
386 | bool is_dfs_referral = false; | ||
359 | 387 | ||
360 | pTcon = cifs_sb->tcon; | 388 | pTcon = cifs_sb->tcon; |
361 | cFYI(1, ("Getting info on %s", search_path)); | 389 | cFYI(1, ("Getting info on %s", search_path)); |
@@ -373,8 +401,12 @@ int cifs_get_inode_info(struct inode **pinode, | |||
373 | if (buf == NULL) | 401 | if (buf == NULL) |
374 | return -ENOMEM; | 402 | return -ENOMEM; |
375 | pfindData = (FILE_ALL_INFO *)buf; | 403 | pfindData = (FILE_ALL_INFO *)buf; |
404 | |||
405 | full_path = cifs_get_search_path(pTcon, search_path); | ||
406 | |||
407 | try_again_CIFSSMBQPathInfo: | ||
376 | /* could do find first instead but this returns more info */ | 408 | /* could do find first instead but this returns more info */ |
377 | rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, | 409 | rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, |
378 | 0 /* not legacy */, | 410 | 0 /* not legacy */, |
379 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 411 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
380 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 412 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -382,7 +414,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
382 | when server claims no NT SMB support and the above call | 414 | when server claims no NT SMB support and the above call |
383 | failed at least once - set flag in tcon or mount */ | 415 | failed at least once - set flag in tcon or mount */ |
384 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { | 416 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { |
385 | rc = SMBQueryInformation(xid, pTcon, search_path, | 417 | rc = SMBQueryInformation(xid, pTcon, full_path, |
386 | pfindData, cifs_sb->local_nls, | 418 | pfindData, cifs_sb->local_nls, |
387 | cifs_sb->mnt_cifs_flags & | 419 | cifs_sb->mnt_cifs_flags & |
388 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 420 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -391,31 +423,15 @@ int cifs_get_inode_info(struct inode **pinode, | |||
391 | } | 423 | } |
392 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 424 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ |
393 | if (rc) { | 425 | if (rc) { |
394 | if (rc == -EREMOTE) { | 426 | if (rc == -EREMOTE && !is_dfs_referral) { |
395 | tmp_path = | 427 | is_dfs_referral = true; |
396 | kmalloc(strnlen | 428 | if (full_path != search_path) { |
397 | (pTcon->treeName, | 429 | kfree(full_path); |
398 | MAX_TREE_SIZE + 1) + | 430 | full_path = search_path; |
399 | strnlen(search_path, MAX_PATHCONF) + 1, | ||
400 | GFP_KERNEL); | ||
401 | if (tmp_path == NULL) { | ||
402 | kfree(buf); | ||
403 | return -ENOMEM; | ||
404 | } | 431 | } |
405 | 432 | goto try_again_CIFSSMBQPathInfo; | |
406 | strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); | ||
407 | strncat(tmp_path, search_path, MAX_PATHCONF); | ||
408 | rc = connect_to_dfs_path(xid, pTcon->ses, | ||
409 | /* treename + */ tmp_path, | ||
410 | cifs_sb->local_nls, | ||
411 | cifs_sb->mnt_cifs_flags & | ||
412 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
413 | kfree(tmp_path); | ||
414 | /* BB fix up inode etc. */ | ||
415 | } else if (rc) { | ||
416 | kfree(buf); | ||
417 | return rc; | ||
418 | } | 433 | } |
434 | goto cgii_exit; | ||
419 | } else { | 435 | } else { |
420 | struct cifsInodeInfo *cifsInfo; | 436 | struct cifsInodeInfo *cifsInfo; |
421 | __u32 attr = le32_to_cpu(pfindData->Attributes); | 437 | __u32 attr = le32_to_cpu(pfindData->Attributes); |
@@ -424,8 +440,8 @@ int cifs_get_inode_info(struct inode **pinode, | |||
424 | if (*pinode == NULL) { | 440 | if (*pinode == NULL) { |
425 | *pinode = new_inode(sb); | 441 | *pinode = new_inode(sb); |
426 | if (*pinode == NULL) { | 442 | if (*pinode == NULL) { |
427 | kfree(buf); | 443 | rc = -ENOMEM; |
428 | return -ENOMEM; | 444 | goto cgii_exit; |
429 | } | 445 | } |
430 | /* Is an i_ino of zero legal? Can we use that to check | 446 | /* Is an i_ino of zero legal? Can we use that to check |
431 | if the server supports returning inode numbers? Are | 447 | if the server supports returning inode numbers? Are |
@@ -559,7 +575,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
559 | /* fill in 0777 bits from ACL */ | 575 | /* fill in 0777 bits from ACL */ |
560 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 576 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
561 | cFYI(1, ("Getting mode bits from ACL")); | 577 | cFYI(1, ("Getting mode bits from ACL")); |
562 | acl_to_uid_mode(inode, search_path); | 578 | acl_to_uid_mode(inode, search_path, pfid); |
563 | } | 579 | } |
564 | #endif | 580 | #endif |
565 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 581 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
@@ -573,8 +589,11 @@ int cifs_get_inode_info(struct inode **pinode, | |||
573 | atomic_set(&cifsInfo->inUse, 1); | 589 | atomic_set(&cifsInfo->inUse, 1); |
574 | } | 590 | } |
575 | 591 | ||
576 | cifs_set_ops(inode); | 592 | cifs_set_ops(inode, is_dfs_referral); |
577 | } | 593 | } |
594 | cgii_exit: | ||
595 | if (full_path != search_path) | ||
596 | kfree(full_path); | ||
578 | kfree(buf); | 597 | kfree(buf); |
579 | return rc; | 598 | return rc; |
580 | } | 599 | } |
@@ -603,7 +622,8 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino) | |||
603 | if (cifs_sb->tcon->unix_ext) | 622 | if (cifs_sb->tcon->unix_ext) |
604 | rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); | 623 | rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); |
605 | else | 624 | else |
606 | rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid); | 625 | rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid, |
626 | NULL); | ||
607 | if (rc && cifs_sb->tcon->ipc) { | 627 | if (rc && cifs_sb->tcon->ipc) { |
608 | cFYI(1, ("ipc connection - fake read inode")); | 628 | cFYI(1, ("ipc connection - fake read inode")); |
609 | inode->i_mode |= S_IFDIR; | 629 | inode->i_mode |= S_IFDIR; |
@@ -804,7 +824,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode, | |||
804 | local_size = tmp_inode->i_size; | 824 | local_size = tmp_inode->i_size; |
805 | 825 | ||
806 | cifs_unix_info_to_inode(tmp_inode, pData, 1); | 826 | cifs_unix_info_to_inode(tmp_inode, pData, 1); |
807 | cifs_set_ops(tmp_inode); | 827 | cifs_set_ops(tmp_inode, false); |
808 | 828 | ||
809 | if (!S_ISREG(tmp_inode->i_mode)) | 829 | if (!S_ISREG(tmp_inode->i_mode)) |
810 | return; | 830 | return; |
@@ -936,7 +956,7 @@ mkdir_get_info: | |||
936 | inode->i_sb, xid); | 956 | inode->i_sb, xid); |
937 | else | 957 | else |
938 | rc = cifs_get_inode_info(&newinode, full_path, NULL, | 958 | rc = cifs_get_inode_info(&newinode, full_path, NULL, |
939 | inode->i_sb, xid); | 959 | inode->i_sb, xid, NULL); |
940 | 960 | ||
941 | if (pTcon->nocase) | 961 | if (pTcon->nocase) |
942 | direntry->d_op = &cifs_ci_dentry_ops; | 962 | direntry->d_op = &cifs_ci_dentry_ops; |
@@ -1218,7 +1238,7 @@ int cifs_revalidate(struct dentry *direntry) | |||
1218 | } | 1238 | } |
1219 | } else { | 1239 | } else { |
1220 | rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL, | 1240 | rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL, |
1221 | direntry->d_sb, xid); | 1241 | direntry->d_sb, xid, NULL); |
1222 | if (rc) { | 1242 | if (rc) { |
1223 | cFYI(1, ("error on getting revalidate info %d", rc)); | 1243 | cFYI(1, ("error on getting revalidate info %d", rc)); |
1224 | /* if (rc != -ENOENT) | 1244 | /* if (rc != -ENOENT) |
@@ -1407,11 +1427,10 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1407 | } | 1427 | } |
1408 | cifsInode = CIFS_I(direntry->d_inode); | 1428 | cifsInode = CIFS_I(direntry->d_inode); |
1409 | 1429 | ||
1410 | /* BB check if we need to refresh inode from server now ? BB */ | 1430 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { |
1411 | |||
1412 | if (attrs->ia_valid & ATTR_SIZE) { | ||
1413 | /* | 1431 | /* |
1414 | Flush data before changing file size on server. If the | 1432 | Flush data before changing file size or changing the last |
1433 | write time of the file on the server. If the | ||
1415 | flush returns error, store it to report later and continue. | 1434 | flush returns error, store it to report later and continue. |
1416 | BB: This should be smarter. Why bother flushing pages that | 1435 | BB: This should be smarter. Why bother flushing pages that |
1417 | will be truncated anyway? Also, should we error out here if | 1436 | will be truncated anyway? Also, should we error out here if |
@@ -1422,7 +1441,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1422 | CIFS_I(direntry->d_inode)->write_behind_rc = rc; | 1441 | CIFS_I(direntry->d_inode)->write_behind_rc = rc; |
1423 | rc = 0; | 1442 | rc = 0; |
1424 | } | 1443 | } |
1444 | } | ||
1425 | 1445 | ||
1446 | if (attrs->ia_valid & ATTR_SIZE) { | ||
1426 | /* To avoid spurious oplock breaks from server, in the case of | 1447 | /* To avoid spurious oplock breaks from server, in the case of |
1427 | inodes that we already have open, avoid doing path based | 1448 | inodes that we already have open, avoid doing path based |
1428 | setting of file size if we can do it by handle. | 1449 | setting of file size if we can do it by handle. |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 1d6fb01b8e6d..d4e7ec93285f 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -205,7 +205,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | |||
205 | inode->i_sb, xid); | 205 | inode->i_sb, xid); |
206 | else | 206 | else |
207 | rc = cifs_get_inode_info(&newinode, full_path, NULL, | 207 | rc = cifs_get_inode_info(&newinode, full_path, NULL, |
208 | inode->i_sb, xid); | 208 | inode->i_sb, xid, NULL); |
209 | 209 | ||
210 | if (rc != 0) { | 210 | if (rc != 0) { |
211 | cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d", | 211 | cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d", |
diff --git a/fs/dquot.c b/fs/dquot.c index 9c7feb62eed1..41b9dbd68b0e 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -1522,8 +1522,8 @@ int vfs_quota_off(struct super_block *sb, int type) | |||
1522 | truncate_inode_pages(&toputinode[cnt]->i_data, 0); | 1522 | truncate_inode_pages(&toputinode[cnt]->i_data, 0); |
1523 | mutex_unlock(&toputinode[cnt]->i_mutex); | 1523 | mutex_unlock(&toputinode[cnt]->i_mutex); |
1524 | mark_inode_dirty(toputinode[cnt]); | 1524 | mark_inode_dirty(toputinode[cnt]); |
1525 | iput(toputinode[cnt]); | ||
1526 | } | 1525 | } |
1526 | iput(toputinode[cnt]); | ||
1527 | mutex_unlock(&dqopt->dqonoff_mutex); | 1527 | mutex_unlock(&dqopt->dqonoff_mutex); |
1528 | } | 1528 | } |
1529 | if (sb->s_bdev) | 1529 | if (sb->s_bdev) |
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index 841a032050a7..5e596583946c 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c | |||
@@ -80,8 +80,8 @@ static void ecryptfs_d_release(struct dentry *dentry) | |||
80 | { | 80 | { |
81 | if (ecryptfs_dentry_to_private(dentry)) { | 81 | if (ecryptfs_dentry_to_private(dentry)) { |
82 | if (ecryptfs_dentry_to_lower(dentry)) { | 82 | if (ecryptfs_dentry_to_lower(dentry)) { |
83 | mntput(ecryptfs_dentry_to_lower_mnt(dentry)); | ||
84 | dput(ecryptfs_dentry_to_lower(dentry)); | 83 | dput(ecryptfs_dentry_to_lower(dentry)); |
84 | mntput(ecryptfs_dentry_to_lower_mnt(dentry)); | ||
85 | } | 85 | } |
86 | kmem_cache_free(ecryptfs_dentry_info_cache, | 86 | kmem_cache_free(ecryptfs_dentry_info_cache, |
87 | ecryptfs_dentry_to_private(dentry)); | 87 | ecryptfs_dentry_to_private(dentry)); |
diff --git a/fs/efs/inode.c b/fs/efs/inode.c index 79e19e5958e1..a8e7797b9477 100644 --- a/fs/efs/inode.c +++ b/fs/efs/inode.c | |||
@@ -140,7 +140,7 @@ struct inode *efs_iget(struct super_block *super, unsigned long ino) | |||
140 | brelse(bh); | 140 | brelse(bh); |
141 | 141 | ||
142 | #ifdef DEBUG | 142 | #ifdef DEBUG |
143 | printk(KERN_DEBUG "EFS: read_inode(): inode %lu, extents %d, mode %o\n", | 143 | printk(KERN_DEBUG "EFS: efs_iget(): inode %lu, extents %d, mode %o\n", |
144 | inode->i_ino, in->numextents, inode->i_mode); | 144 | inode->i_ino, in->numextents, inode->i_mode); |
145 | #endif | 145 | #endif |
146 | 146 | ||
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index d34e9967430a..a754d1848173 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c | |||
@@ -37,7 +37,7 @@ ext3_acl_from_disk(const void *value, size_t size) | |||
37 | return ERR_PTR(-EINVAL); | 37 | return ERR_PTR(-EINVAL); |
38 | if (count == 0) | 38 | if (count == 0) |
39 | return NULL; | 39 | return NULL; |
40 | acl = posix_acl_alloc(count, GFP_KERNEL); | 40 | acl = posix_acl_alloc(count, GFP_NOFS); |
41 | if (!acl) | 41 | if (!acl) |
42 | return ERR_PTR(-ENOMEM); | 42 | return ERR_PTR(-ENOMEM); |
43 | for (n=0; n < count; n++) { | 43 | for (n=0; n < count; n++) { |
@@ -91,7 +91,7 @@ ext3_acl_to_disk(const struct posix_acl *acl, size_t *size) | |||
91 | 91 | ||
92 | *size = ext3_acl_size(acl->a_count); | 92 | *size = ext3_acl_size(acl->a_count); |
93 | ext_acl = kmalloc(sizeof(ext3_acl_header) + acl->a_count * | 93 | ext_acl = kmalloc(sizeof(ext3_acl_header) + acl->a_count * |
94 | sizeof(ext3_acl_entry), GFP_KERNEL); | 94 | sizeof(ext3_acl_entry), GFP_NOFS); |
95 | if (!ext_acl) | 95 | if (!ext_acl) |
96 | return ERR_PTR(-ENOMEM); | 96 | return ERR_PTR(-ENOMEM); |
97 | ext_acl->a_version = cpu_to_le32(EXT3_ACL_VERSION); | 97 | ext_acl->a_version = cpu_to_le32(EXT3_ACL_VERSION); |
@@ -187,7 +187,7 @@ ext3_get_acl(struct inode *inode, int type) | |||
187 | } | 187 | } |
188 | retval = ext3_xattr_get(inode, name_index, "", NULL, 0); | 188 | retval = ext3_xattr_get(inode, name_index, "", NULL, 0); |
189 | if (retval > 0) { | 189 | if (retval > 0) { |
190 | value = kmalloc(retval, GFP_KERNEL); | 190 | value = kmalloc(retval, GFP_NOFS); |
191 | if (!value) | 191 | if (!value) |
192 | return ERR_PTR(-ENOMEM); | 192 | return ERR_PTR(-ENOMEM); |
193 | retval = ext3_xattr_get(inode, name_index, "", value, retval); | 193 | retval = ext3_xattr_get(inode, name_index, "", value, retval); |
@@ -335,7 +335,7 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) | |||
335 | if (error) | 335 | if (error) |
336 | goto cleanup; | 336 | goto cleanup; |
337 | } | 337 | } |
338 | clone = posix_acl_clone(acl, GFP_KERNEL); | 338 | clone = posix_acl_clone(acl, GFP_NOFS); |
339 | error = -ENOMEM; | 339 | error = -ENOMEM; |
340 | if (!clone) | 340 | if (!clone) |
341 | goto cleanup; | 341 | goto cleanup; |
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 9397d779c43d..0e97b6e07cb0 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -485,7 +485,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
485 | goto exit_dindj; | 485 | goto exit_dindj; |
486 | 486 | ||
487 | n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *), | 487 | n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *), |
488 | GFP_KERNEL); | 488 | GFP_NOFS); |
489 | if (!n_group_desc) { | 489 | if (!n_group_desc) { |
490 | err = -ENOMEM; | 490 | err = -ENOMEM; |
491 | ext3_warning (sb, __FUNCTION__, | 491 | ext3_warning (sb, __FUNCTION__, |
@@ -568,7 +568,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, | |||
568 | int res, i; | 568 | int res, i; |
569 | int err; | 569 | int err; |
570 | 570 | ||
571 | primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_KERNEL); | 571 | primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_NOFS); |
572 | if (!primary) | 572 | if (!primary) |
573 | return -ENOMEM; | 573 | return -ENOMEM; |
574 | 574 | ||
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index fb89c299bece..a6ea4d6a8bb2 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c | |||
@@ -728,7 +728,7 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, | |||
728 | ce = NULL; | 728 | ce = NULL; |
729 | } | 729 | } |
730 | ea_bdebug(bs->bh, "cloning"); | 730 | ea_bdebug(bs->bh, "cloning"); |
731 | s->base = kmalloc(bs->bh->b_size, GFP_KERNEL); | 731 | s->base = kmalloc(bs->bh->b_size, GFP_NOFS); |
732 | error = -ENOMEM; | 732 | error = -ENOMEM; |
733 | if (s->base == NULL) | 733 | if (s->base == NULL) |
734 | goto cleanup; | 734 | goto cleanup; |
@@ -740,7 +740,7 @@ ext3_xattr_block_set(handle_t *handle, struct inode *inode, | |||
740 | } | 740 | } |
741 | } else { | 741 | } else { |
742 | /* Allocate a buffer where we construct the new block. */ | 742 | /* Allocate a buffer where we construct the new block. */ |
743 | s->base = kzalloc(sb->s_blocksize, GFP_KERNEL); | 743 | s->base = kzalloc(sb->s_blocksize, GFP_NOFS); |
744 | /* assert(header == s->base) */ | 744 | /* assert(header == s->base) */ |
745 | error = -ENOMEM; | 745 | error = -ENOMEM; |
746 | if (s->base == NULL) | 746 | if (s->base == NULL) |
diff --git a/fs/file_table.c b/fs/file_table.c index 6d27befe2d48..986ff4ed0a7c 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -83,6 +83,12 @@ int proc_nr_files(ctl_table *table, int write, struct file *filp, | |||
83 | /* Find an unused file structure and return a pointer to it. | 83 | /* Find an unused file structure and return a pointer to it. |
84 | * Returns NULL, if there are no more free file structures or | 84 | * Returns NULL, if there are no more free file structures or |
85 | * we run out of memory. | 85 | * we run out of memory. |
86 | * | ||
87 | * Be very careful using this. You are responsible for | ||
88 | * getting write access to any mount that you might assign | ||
89 | * to this filp, if it is opened for write. If this is not | ||
90 | * done, you will imbalance int the mount's writer count | ||
91 | * and a warning at __fput() time. | ||
86 | */ | 92 | */ |
87 | struct file *get_empty_filp(void) | 93 | struct file *get_empty_filp(void) |
88 | { | 94 | { |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c0076077d338..06557679ca41 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -751,7 +751,7 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int | |||
751 | EXPORT_SYMBOL(generic_osync_inode); | 751 | EXPORT_SYMBOL(generic_osync_inode); |
752 | 752 | ||
753 | /** | 753 | /** |
754 | * writeback_acquire: attempt to get exclusive writeback access to a device | 754 | * writeback_acquire - attempt to get exclusive writeback access to a device |
755 | * @bdi: the device's backing_dev_info structure | 755 | * @bdi: the device's backing_dev_info structure |
756 | * | 756 | * |
757 | * It is a waste of resources to have more than one pdflush thread blocked on | 757 | * It is a waste of resources to have more than one pdflush thread blocked on |
@@ -768,7 +768,7 @@ int writeback_acquire(struct backing_dev_info *bdi) | |||
768 | } | 768 | } |
769 | 769 | ||
770 | /** | 770 | /** |
771 | * writeback_in_progress: determine whether there is writeback in progress | 771 | * writeback_in_progress - determine whether there is writeback in progress |
772 | * @bdi: the device's backing_dev_info structure. | 772 | * @bdi: the device's backing_dev_info structure. |
773 | * | 773 | * |
774 | * Determine whether there is writeback in progress against a backing device. | 774 | * Determine whether there is writeback in progress against a backing device. |
@@ -779,7 +779,7 @@ int writeback_in_progress(struct backing_dev_info *bdi) | |||
779 | } | 779 | } |
780 | 780 | ||
781 | /** | 781 | /** |
782 | * writeback_release: relinquish exclusive writeback access against a device. | 782 | * writeback_release - relinquish exclusive writeback access against a device. |
783 | * @bdi: the device's backing_dev_info structure | 783 | * @bdi: the device's backing_dev_info structure |
784 | */ | 784 | */ |
785 | void writeback_release(struct backing_dev_info *bdi) | 785 | void writeback_release(struct backing_dev_info *bdi) |
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index a1e1f0f61aa5..8601d8ef3b55 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c | |||
@@ -1,23 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/fs.h> | 6 | #include <linux/ctype.h> |
7 | #include <linux/dcache.h> | ||
7 | #include <linux/file.h> | 8 | #include <linux/file.h> |
8 | #include <linux/module.h> | 9 | #include <linux/fs.h> |
9 | #include <linux/init.h> | 10 | #include <linux/init.h> |
10 | #include <linux/slab.h> | ||
11 | #include <linux/list.h> | ||
12 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
13 | #include <linux/ctype.h> | 12 | #include <linux/list.h> |
14 | #include <linux/dcache.h> | 13 | #include <linux/module.h> |
14 | #include <linux/mount.h> | ||
15 | #include <linux/slab.h> | ||
15 | #include <linux/statfs.h> | 16 | #include <linux/statfs.h> |
17 | #include <linux/types.h> | ||
16 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
17 | #include <asm/fcntl.h> | ||
18 | #include "os.h" | 19 | #include "os.h" |
19 | 20 | ||
20 | static int init_inode(struct inode *inode, struct dentry *dentry); | 21 | static struct inode *get_inode(struct super_block *, struct dentry *); |
21 | 22 | ||
22 | struct hppfs_data { | 23 | struct hppfs_data { |
23 | struct list_head list; | 24 | struct list_head list; |
@@ -51,14 +52,14 @@ static int is_pid(struct dentry *dentry) | |||
51 | int i; | 52 | int i; |
52 | 53 | ||
53 | sb = dentry->d_sb; | 54 | sb = dentry->d_sb; |
54 | if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) | 55 | if ((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) |
55 | return(0); | 56 | return 0; |
56 | 57 | ||
57 | for(i = 0; i < dentry->d_name.len; i++){ | 58 | for (i = 0; i < dentry->d_name.len; i++) { |
58 | if(!isdigit(dentry->d_name.name[i])) | 59 | if (!isdigit(dentry->d_name.name[i])) |
59 | return(0); | 60 | return 0; |
60 | } | 61 | } |
61 | return(1); | 62 | return 1; |
62 | } | 63 | } |
63 | 64 | ||
64 | static char *dentry_name(struct dentry *dentry, int extra) | 65 | static char *dentry_name(struct dentry *dentry, int extra) |
@@ -70,8 +71,8 @@ static char *dentry_name(struct dentry *dentry, int extra) | |||
70 | 71 | ||
71 | len = 0; | 72 | len = 0; |
72 | parent = dentry; | 73 | parent = dentry; |
73 | while(parent->d_parent != parent){ | 74 | while (parent->d_parent != parent) { |
74 | if(is_pid(parent)) | 75 | if (is_pid(parent)) |
75 | len += strlen("pid") + 1; | 76 | len += strlen("pid") + 1; |
76 | else len += parent->d_name.len + 1; | 77 | else len += parent->d_name.len + 1; |
77 | parent = parent->d_parent; | 78 | parent = parent->d_parent; |
@@ -80,12 +81,13 @@ static char *dentry_name(struct dentry *dentry, int extra) | |||
80 | root = "proc"; | 81 | root = "proc"; |
81 | len += strlen(root); | 82 | len += strlen(root); |
82 | name = kmalloc(len + extra + 1, GFP_KERNEL); | 83 | name = kmalloc(len + extra + 1, GFP_KERNEL); |
83 | if(name == NULL) return(NULL); | 84 | if (name == NULL) |
85 | return NULL; | ||
84 | 86 | ||
85 | name[len] = '\0'; | 87 | name[len] = '\0'; |
86 | parent = dentry; | 88 | parent = dentry; |
87 | while(parent->d_parent != parent){ | 89 | while (parent->d_parent != parent) { |
88 | if(is_pid(parent)){ | 90 | if (is_pid(parent)) { |
89 | seg_name = "pid"; | 91 | seg_name = "pid"; |
90 | seg_len = strlen("pid"); | 92 | seg_len = strlen("pid"); |
91 | } | 93 | } |
@@ -100,27 +102,25 @@ static char *dentry_name(struct dentry *dentry, int extra) | |||
100 | parent = parent->d_parent; | 102 | parent = parent->d_parent; |
101 | } | 103 | } |
102 | strncpy(name, root, strlen(root)); | 104 | strncpy(name, root, strlen(root)); |
103 | return(name); | 105 | return name; |
104 | } | 106 | } |
105 | 107 | ||
106 | struct dentry_operations hppfs_dentry_ops = { | ||
107 | }; | ||
108 | |||
109 | static int file_removed(struct dentry *dentry, const char *file) | 108 | static int file_removed(struct dentry *dentry, const char *file) |
110 | { | 109 | { |
111 | char *host_file; | 110 | char *host_file; |
112 | int extra, fd; | 111 | int extra, fd; |
113 | 112 | ||
114 | extra = 0; | 113 | extra = 0; |
115 | if(file != NULL) extra += strlen(file) + 1; | 114 | if (file != NULL) |
115 | extra += strlen(file) + 1; | ||
116 | 116 | ||
117 | host_file = dentry_name(dentry, extra + strlen("/remove")); | 117 | host_file = dentry_name(dentry, extra + strlen("/remove")); |
118 | if(host_file == NULL){ | 118 | if (host_file == NULL) { |
119 | printk("file_removed : allocation failed\n"); | 119 | printk(KERN_ERR "file_removed : allocation failed\n"); |
120 | return(-ENOMEM); | 120 | return -ENOMEM; |
121 | } | 121 | } |
122 | 122 | ||
123 | if(file != NULL){ | 123 | if (file != NULL) { |
124 | strcat(host_file, "/"); | 124 | strcat(host_file, "/"); |
125 | strcat(host_file, file); | 125 | strcat(host_file, file); |
126 | } | 126 | } |
@@ -128,45 +128,11 @@ static int file_removed(struct dentry *dentry, const char *file) | |||
128 | 128 | ||
129 | fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); | 129 | fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); |
130 | kfree(host_file); | 130 | kfree(host_file); |
131 | if(fd > 0){ | 131 | if (fd > 0) { |
132 | os_close_file(fd); | 132 | os_close_file(fd); |
133 | return(1); | 133 | return 1; |
134 | } | ||
135 | return(0); | ||
136 | } | ||
137 | |||
138 | static void hppfs_read_inode(struct inode *ino) | ||
139 | { | ||
140 | struct inode *proc_ino; | ||
141 | |||
142 | if(HPPFS_I(ino)->proc_dentry == NULL) | ||
143 | return; | ||
144 | |||
145 | proc_ino = HPPFS_I(ino)->proc_dentry->d_inode; | ||
146 | ino->i_uid = proc_ino->i_uid; | ||
147 | ino->i_gid = proc_ino->i_gid; | ||
148 | ino->i_atime = proc_ino->i_atime; | ||
149 | ino->i_mtime = proc_ino->i_mtime; | ||
150 | ino->i_ctime = proc_ino->i_ctime; | ||
151 | ino->i_ino = proc_ino->i_ino; | ||
152 | ino->i_mode = proc_ino->i_mode; | ||
153 | ino->i_nlink = proc_ino->i_nlink; | ||
154 | ino->i_size = proc_ino->i_size; | ||
155 | ino->i_blocks = proc_ino->i_blocks; | ||
156 | } | ||
157 | |||
158 | static struct inode *hppfs_iget(struct super_block *sb) | ||
159 | { | ||
160 | struct inode *inode; | ||
161 | |||
162 | inode = iget_locked(sb, 0); | ||
163 | if (!inode) | ||
164 | return ERR_PTR(-ENOMEM); | ||
165 | if (inode->i_state & I_NEW) { | ||
166 | hppfs_read_inode(inode); | ||
167 | unlock_new_inode(inode); | ||
168 | } | 134 | } |
169 | return inode; | 135 | return 0; |
170 | } | 136 | } |
171 | 137 | ||
172 | static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | 138 | static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, |
@@ -177,55 +143,45 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | |||
177 | int err, deleted; | 143 | int err, deleted; |
178 | 144 | ||
179 | deleted = file_removed(dentry, NULL); | 145 | deleted = file_removed(dentry, NULL); |
180 | if(deleted < 0) | 146 | if (deleted < 0) |
181 | return(ERR_PTR(deleted)); | 147 | return ERR_PTR(deleted); |
182 | else if(deleted) | 148 | else if (deleted) |
183 | return(ERR_PTR(-ENOENT)); | 149 | return ERR_PTR(-ENOENT); |
184 | 150 | ||
185 | err = -ENOMEM; | 151 | err = -ENOMEM; |
186 | parent = HPPFS_I(ino)->proc_dentry; | 152 | parent = HPPFS_I(ino)->proc_dentry; |
187 | mutex_lock(&parent->d_inode->i_mutex); | 153 | mutex_lock(&parent->d_inode->i_mutex); |
188 | proc_dentry = d_lookup(parent, &dentry->d_name); | 154 | proc_dentry = d_lookup(parent, &dentry->d_name); |
189 | if(proc_dentry == NULL){ | 155 | if (proc_dentry == NULL) { |
190 | proc_dentry = d_alloc(parent, &dentry->d_name); | 156 | proc_dentry = d_alloc(parent, &dentry->d_name); |
191 | if(proc_dentry == NULL){ | 157 | if (proc_dentry == NULL) { |
192 | mutex_unlock(&parent->d_inode->i_mutex); | 158 | mutex_unlock(&parent->d_inode->i_mutex); |
193 | goto out; | 159 | goto out; |
194 | } | 160 | } |
195 | new = (*parent->d_inode->i_op->lookup)(parent->d_inode, | 161 | new = (*parent->d_inode->i_op->lookup)(parent->d_inode, |
196 | proc_dentry, NULL); | 162 | proc_dentry, NULL); |
197 | if(new){ | 163 | if (new) { |
198 | dput(proc_dentry); | 164 | dput(proc_dentry); |
199 | proc_dentry = new; | 165 | proc_dentry = new; |
200 | } | 166 | } |
201 | } | 167 | } |
202 | mutex_unlock(&parent->d_inode->i_mutex); | 168 | mutex_unlock(&parent->d_inode->i_mutex); |
203 | 169 | ||
204 | if(IS_ERR(proc_dentry)) | 170 | if (IS_ERR(proc_dentry)) |
205 | return(proc_dentry); | 171 | return proc_dentry; |
206 | 172 | ||
207 | inode = hppfs_iget(ino->i_sb); | 173 | err = -ENOMEM; |
208 | if (IS_ERR(inode)) { | 174 | inode = get_inode(ino->i_sb, proc_dentry); |
209 | err = PTR_ERR(inode); | 175 | if (!inode) |
210 | goto out_dput; | 176 | goto out_dput; |
211 | } | ||
212 | |||
213 | err = init_inode(inode, proc_dentry); | ||
214 | if(err) | ||
215 | goto out_put; | ||
216 | |||
217 | hppfs_read_inode(inode); | ||
218 | 177 | ||
219 | d_add(dentry, inode); | 178 | d_add(dentry, inode); |
220 | dentry->d_op = &hppfs_dentry_ops; | 179 | return NULL; |
221 | return(NULL); | ||
222 | 180 | ||
223 | out_put: | ||
224 | iput(inode); | ||
225 | out_dput: | 181 | out_dput: |
226 | dput(proc_dentry); | 182 | dput(proc_dentry); |
227 | out: | 183 | out: |
228 | return(ERR_PTR(err)); | 184 | return ERR_PTR(err); |
229 | } | 185 | } |
230 | 186 | ||
231 | static const struct inode_operations hppfs_file_iops = { | 187 | static const struct inode_operations hppfs_file_iops = { |
@@ -239,15 +195,16 @@ static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, | |||
239 | 195 | ||
240 | read = file->f_path.dentry->d_inode->i_fop->read; | 196 | read = file->f_path.dentry->d_inode->i_fop->read; |
241 | 197 | ||
242 | if(!is_user) | 198 | if (!is_user) |
243 | set_fs(KERNEL_DS); | 199 | set_fs(KERNEL_DS); |
244 | 200 | ||
245 | n = (*read)(file, buf, count, &file->f_pos); | 201 | n = (*read)(file, buf, count, &file->f_pos); |
246 | 202 | ||
247 | if(!is_user) | 203 | if (!is_user) |
248 | set_fs(USER_DS); | 204 | set_fs(USER_DS); |
249 | 205 | ||
250 | if(ppos) *ppos = file->f_pos; | 206 | if (ppos) |
207 | *ppos = file->f_pos; | ||
251 | return n; | 208 | return n; |
252 | } | 209 | } |
253 | 210 | ||
@@ -259,24 +216,23 @@ static ssize_t hppfs_read_file(int fd, char __user *buf, ssize_t count) | |||
259 | 216 | ||
260 | n = -ENOMEM; | 217 | n = -ENOMEM; |
261 | new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 218 | new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
262 | if(new_buf == NULL){ | 219 | if (new_buf == NULL) { |
263 | printk("hppfs_read_file : kmalloc failed\n"); | 220 | printk(KERN_ERR "hppfs_read_file : kmalloc failed\n"); |
264 | goto out; | 221 | goto out; |
265 | } | 222 | } |
266 | n = 0; | 223 | n = 0; |
267 | while(count > 0){ | 224 | while (count > 0) { |
268 | cur = min_t(ssize_t, count, PAGE_SIZE); | 225 | cur = min_t(ssize_t, count, PAGE_SIZE); |
269 | err = os_read_file(fd, new_buf, cur); | 226 | err = os_read_file(fd, new_buf, cur); |
270 | if(err < 0){ | 227 | if (err < 0) { |
271 | printk("hppfs_read : read failed, errno = %d\n", | 228 | printk(KERN_ERR "hppfs_read : read failed, " |
272 | err); | 229 | "errno = %d\n", err); |
273 | n = err; | 230 | n = err; |
274 | goto out_free; | 231 | goto out_free; |
275 | } | 232 | } else if (err == 0) |
276 | else if(err == 0) | ||
277 | break; | 233 | break; |
278 | 234 | ||
279 | if(copy_to_user(buf, new_buf, err)){ | 235 | if (copy_to_user(buf, new_buf, err)) { |
280 | n = -EFAULT; | 236 | n = -EFAULT; |
281 | goto out_free; | 237 | goto out_free; |
282 | } | 238 | } |
@@ -297,35 +253,36 @@ static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, | |||
297 | loff_t off; | 253 | loff_t off; |
298 | int err; | 254 | int err; |
299 | 255 | ||
300 | if(hppfs->contents != NULL){ | 256 | if (hppfs->contents != NULL) { |
301 | if(*ppos >= hppfs->len) return(0); | 257 | if (*ppos >= hppfs->len) |
258 | return 0; | ||
302 | 259 | ||
303 | data = hppfs->contents; | 260 | data = hppfs->contents; |
304 | off = *ppos; | 261 | off = *ppos; |
305 | while(off >= sizeof(data->contents)){ | 262 | while (off >= sizeof(data->contents)) { |
306 | data = list_entry(data->list.next, struct hppfs_data, | 263 | data = list_entry(data->list.next, struct hppfs_data, |
307 | list); | 264 | list); |
308 | off -= sizeof(data->contents); | 265 | off -= sizeof(data->contents); |
309 | } | 266 | } |
310 | 267 | ||
311 | if(off + count > hppfs->len) | 268 | if (off + count > hppfs->len) |
312 | count = hppfs->len - off; | 269 | count = hppfs->len - off; |
313 | copy_to_user(buf, &data->contents[off], count); | 270 | copy_to_user(buf, &data->contents[off], count); |
314 | *ppos += count; | 271 | *ppos += count; |
315 | } | 272 | } else if (hppfs->host_fd != -1) { |
316 | else if(hppfs->host_fd != -1){ | ||
317 | err = os_seek_file(hppfs->host_fd, *ppos); | 273 | err = os_seek_file(hppfs->host_fd, *ppos); |
318 | if(err){ | 274 | if (err) { |
319 | printk("hppfs_read : seek failed, errno = %d\n", err); | 275 | printk(KERN_ERR "hppfs_read : seek failed, " |
320 | return(err); | 276 | "errno = %d\n", err); |
277 | return err; | ||
321 | } | 278 | } |
322 | count = hppfs_read_file(hppfs->host_fd, buf, count); | 279 | count = hppfs_read_file(hppfs->host_fd, buf, count); |
323 | if(count > 0) | 280 | if (count > 0) |
324 | *ppos += count; | 281 | *ppos += count; |
325 | } | 282 | } |
326 | else count = read_proc(hppfs->proc_file, buf, count, ppos, 1); | 283 | else count = read_proc(hppfs->proc_file, buf, count, ppos, 1); |
327 | 284 | ||
328 | return(count); | 285 | return count; |
329 | } | 286 | } |
330 | 287 | ||
331 | static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len, | 288 | static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len, |
@@ -342,7 +299,7 @@ static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len | |||
342 | err = (*write)(proc_file, buf, len, &proc_file->f_pos); | 299 | err = (*write)(proc_file, buf, len, &proc_file->f_pos); |
343 | file->f_pos = proc_file->f_pos; | 300 | file->f_pos = proc_file->f_pos; |
344 | 301 | ||
345 | return(err); | 302 | return err; |
346 | } | 303 | } |
347 | 304 | ||
348 | static int open_host_sock(char *host_file, int *filter_out) | 305 | static int open_host_sock(char *host_file, int *filter_out) |
@@ -354,13 +311,13 @@ static int open_host_sock(char *host_file, int *filter_out) | |||
354 | strcpy(end, "/rw"); | 311 | strcpy(end, "/rw"); |
355 | *filter_out = 1; | 312 | *filter_out = 1; |
356 | fd = os_connect_socket(host_file); | 313 | fd = os_connect_socket(host_file); |
357 | if(fd > 0) | 314 | if (fd > 0) |
358 | return(fd); | 315 | return fd; |
359 | 316 | ||
360 | strcpy(end, "/r"); | 317 | strcpy(end, "/r"); |
361 | *filter_out = 0; | 318 | *filter_out = 0; |
362 | fd = os_connect_socket(host_file); | 319 | fd = os_connect_socket(host_file); |
363 | return(fd); | 320 | return fd; |
364 | } | 321 | } |
365 | 322 | ||
366 | static void free_contents(struct hppfs_data *head) | 323 | static void free_contents(struct hppfs_data *head) |
@@ -368,9 +325,10 @@ static void free_contents(struct hppfs_data *head) | |||
368 | struct hppfs_data *data; | 325 | struct hppfs_data *data; |
369 | struct list_head *ele, *next; | 326 | struct list_head *ele, *next; |
370 | 327 | ||
371 | if(head == NULL) return; | 328 | if (head == NULL) |
329 | return; | ||
372 | 330 | ||
373 | list_for_each_safe(ele, next, &head->list){ | 331 | list_for_each_safe(ele, next, &head->list) { |
374 | data = list_entry(ele, struct hppfs_data, list); | 332 | data = list_entry(ele, struct hppfs_data, list); |
375 | kfree(data); | 333 | kfree(data); |
376 | } | 334 | } |
@@ -387,8 +345,8 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter, | |||
387 | 345 | ||
388 | err = -ENOMEM; | 346 | err = -ENOMEM; |
389 | data = kmalloc(sizeof(*data), GFP_KERNEL); | 347 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
390 | if(data == NULL){ | 348 | if (data == NULL) { |
391 | printk("hppfs_get_data : head allocation failed\n"); | 349 | printk(KERN_ERR "hppfs_get_data : head allocation failed\n"); |
392 | goto failed; | 350 | goto failed; |
393 | } | 351 | } |
394 | 352 | ||
@@ -397,36 +355,36 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter, | |||
397 | head = data; | 355 | head = data; |
398 | *size_out = 0; | 356 | *size_out = 0; |
399 | 357 | ||
400 | if(filter){ | 358 | if (filter) { |
401 | while((n = read_proc(proc_file, data->contents, | 359 | while ((n = read_proc(proc_file, data->contents, |
402 | sizeof(data->contents), NULL, 0)) > 0) | 360 | sizeof(data->contents), NULL, 0)) > 0) |
403 | os_write_file(fd, data->contents, n); | 361 | os_write_file(fd, data->contents, n); |
404 | err = os_shutdown_socket(fd, 0, 1); | 362 | err = os_shutdown_socket(fd, 0, 1); |
405 | if(err){ | 363 | if (err) { |
406 | printk("hppfs_get_data : failed to shut down " | 364 | printk(KERN_ERR "hppfs_get_data : failed to shut down " |
407 | "socket\n"); | 365 | "socket\n"); |
408 | goto failed_free; | 366 | goto failed_free; |
409 | } | 367 | } |
410 | } | 368 | } |
411 | while(1){ | 369 | while (1) { |
412 | n = os_read_file(fd, data->contents, sizeof(data->contents)); | 370 | n = os_read_file(fd, data->contents, sizeof(data->contents)); |
413 | if(n < 0){ | 371 | if (n < 0) { |
414 | err = n; | 372 | err = n; |
415 | printk("hppfs_get_data : read failed, errno = %d\n", | 373 | printk(KERN_ERR "hppfs_get_data : read failed, " |
416 | err); | 374 | "errno = %d\n", err); |
417 | goto failed_free; | 375 | goto failed_free; |
418 | } | 376 | } else if (n == 0) |
419 | else if(n == 0) | ||
420 | break; | 377 | break; |
421 | 378 | ||
422 | *size_out += n; | 379 | *size_out += n; |
423 | 380 | ||
424 | if(n < sizeof(data->contents)) | 381 | if (n < sizeof(data->contents)) |
425 | break; | 382 | break; |
426 | 383 | ||
427 | new = kmalloc(sizeof(*data), GFP_KERNEL); | 384 | new = kmalloc(sizeof(*data), GFP_KERNEL); |
428 | if(new == 0){ | 385 | if (new == 0) { |
429 | printk("hppfs_get_data : data allocation failed\n"); | 386 | printk(KERN_ERR "hppfs_get_data : data allocation " |
387 | "failed\n"); | ||
430 | err = -ENOMEM; | 388 | err = -ENOMEM; |
431 | goto failed_free; | 389 | goto failed_free; |
432 | } | 390 | } |
@@ -435,12 +393,12 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter, | |||
435 | list_add(&new->list, &data->list); | 393 | list_add(&new->list, &data->list); |
436 | data = new; | 394 | data = new; |
437 | } | 395 | } |
438 | return(head); | 396 | return head; |
439 | 397 | ||
440 | failed_free: | 398 | failed_free: |
441 | free_contents(head); | 399 | free_contents(head); |
442 | failed: | 400 | failed: |
443 | return(ERR_PTR(err)); | 401 | return ERR_PTR(err); |
444 | } | 402 | } |
445 | 403 | ||
446 | static struct hppfs_private *hppfs_data(void) | 404 | static struct hppfs_private *hppfs_data(void) |
@@ -448,77 +406,79 @@ static struct hppfs_private *hppfs_data(void) | |||
448 | struct hppfs_private *data; | 406 | struct hppfs_private *data; |
449 | 407 | ||
450 | data = kmalloc(sizeof(*data), GFP_KERNEL); | 408 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
451 | if(data == NULL) | 409 | if (data == NULL) |
452 | return(data); | 410 | return data; |
453 | 411 | ||
454 | *data = ((struct hppfs_private ) { .host_fd = -1, | 412 | *data = ((struct hppfs_private ) { .host_fd = -1, |
455 | .len = -1, | 413 | .len = -1, |
456 | .contents = NULL } ); | 414 | .contents = NULL } ); |
457 | return(data); | 415 | return data; |
458 | } | 416 | } |
459 | 417 | ||
460 | static int file_mode(int fmode) | 418 | static int file_mode(int fmode) |
461 | { | 419 | { |
462 | if(fmode == (FMODE_READ | FMODE_WRITE)) | 420 | if (fmode == (FMODE_READ | FMODE_WRITE)) |
463 | return(O_RDWR); | 421 | return O_RDWR; |
464 | if(fmode == FMODE_READ) | 422 | if (fmode == FMODE_READ) |
465 | return(O_RDONLY); | 423 | return O_RDONLY; |
466 | if(fmode == FMODE_WRITE) | 424 | if (fmode == FMODE_WRITE) |
467 | return(O_WRONLY); | 425 | return O_WRONLY; |
468 | return(0); | 426 | return 0; |
469 | } | 427 | } |
470 | 428 | ||
471 | static int hppfs_open(struct inode *inode, struct file *file) | 429 | static int hppfs_open(struct inode *inode, struct file *file) |
472 | { | 430 | { |
473 | struct hppfs_private *data; | 431 | struct hppfs_private *data; |
474 | struct dentry *proc_dentry; | 432 | struct dentry *proc_dentry; |
433 | struct vfsmount *proc_mnt; | ||
475 | char *host_file; | 434 | char *host_file; |
476 | int err, fd, type, filter; | 435 | int err, fd, type, filter; |
477 | 436 | ||
478 | err = -ENOMEM; | 437 | err = -ENOMEM; |
479 | data = hppfs_data(); | 438 | data = hppfs_data(); |
480 | if(data == NULL) | 439 | if (data == NULL) |
481 | goto out; | 440 | goto out; |
482 | 441 | ||
483 | host_file = dentry_name(file->f_path.dentry, strlen("/rw")); | 442 | host_file = dentry_name(file->f_path.dentry, strlen("/rw")); |
484 | if(host_file == NULL) | 443 | if (host_file == NULL) |
485 | goto out_free2; | 444 | goto out_free2; |
486 | 445 | ||
487 | proc_dentry = HPPFS_I(inode)->proc_dentry; | 446 | proc_dentry = HPPFS_I(inode)->proc_dentry; |
447 | proc_mnt = inode->i_sb->s_fs_info; | ||
488 | 448 | ||
489 | /* XXX This isn't closed anywhere */ | 449 | /* XXX This isn't closed anywhere */ |
490 | data->proc_file = dentry_open(dget(proc_dentry), NULL, | 450 | data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), |
491 | file_mode(file->f_mode)); | 451 | file_mode(file->f_mode)); |
492 | err = PTR_ERR(data->proc_file); | 452 | err = PTR_ERR(data->proc_file); |
493 | if(IS_ERR(data->proc_file)) | 453 | if (IS_ERR(data->proc_file)) |
494 | goto out_free1; | 454 | goto out_free1; |
495 | 455 | ||
496 | type = os_file_type(host_file); | 456 | type = os_file_type(host_file); |
497 | if(type == OS_TYPE_FILE){ | 457 | if (type == OS_TYPE_FILE) { |
498 | fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); | 458 | fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); |
499 | if(fd >= 0) | 459 | if (fd >= 0) |
500 | data->host_fd = fd; | 460 | data->host_fd = fd; |
501 | else printk("hppfs_open : failed to open '%s', errno = %d\n", | 461 | else |
502 | host_file, -fd); | 462 | printk(KERN_ERR "hppfs_open : failed to open '%s', " |
463 | "errno = %d\n", host_file, -fd); | ||
503 | 464 | ||
504 | data->contents = NULL; | 465 | data->contents = NULL; |
505 | } | 466 | } else if (type == OS_TYPE_DIR) { |
506 | else if(type == OS_TYPE_DIR){ | ||
507 | fd = open_host_sock(host_file, &filter); | 467 | fd = open_host_sock(host_file, &filter); |
508 | if(fd > 0){ | 468 | if (fd > 0) { |
509 | data->contents = hppfs_get_data(fd, filter, | 469 | data->contents = hppfs_get_data(fd, filter, |
510 | data->proc_file, | 470 | data->proc_file, |
511 | file, &data->len); | 471 | file, &data->len); |
512 | if(!IS_ERR(data->contents)) | 472 | if (!IS_ERR(data->contents)) |
513 | data->host_fd = fd; | 473 | data->host_fd = fd; |
514 | } | 474 | } else |
515 | else printk("hppfs_open : failed to open a socket in " | 475 | printk(KERN_ERR "hppfs_open : failed to open a socket " |
516 | "'%s', errno = %d\n", host_file, -fd); | 476 | "in '%s', errno = %d\n", host_file, -fd); |
517 | } | 477 | } |
518 | kfree(host_file); | 478 | kfree(host_file); |
519 | 479 | ||
520 | file->private_data = data; | 480 | file->private_data = data; |
521 | return(0); | 481 | return 0; |
522 | 482 | ||
523 | out_free1: | 483 | out_free1: |
524 | kfree(host_file); | 484 | kfree(host_file); |
@@ -526,34 +486,36 @@ static int hppfs_open(struct inode *inode, struct file *file) | |||
526 | free_contents(data->contents); | 486 | free_contents(data->contents); |
527 | kfree(data); | 487 | kfree(data); |
528 | out: | 488 | out: |
529 | return(err); | 489 | return err; |
530 | } | 490 | } |
531 | 491 | ||
532 | static int hppfs_dir_open(struct inode *inode, struct file *file) | 492 | static int hppfs_dir_open(struct inode *inode, struct file *file) |
533 | { | 493 | { |
534 | struct hppfs_private *data; | 494 | struct hppfs_private *data; |
535 | struct dentry *proc_dentry; | 495 | struct dentry *proc_dentry; |
496 | struct vfsmount *proc_mnt; | ||
536 | int err; | 497 | int err; |
537 | 498 | ||
538 | err = -ENOMEM; | 499 | err = -ENOMEM; |
539 | data = hppfs_data(); | 500 | data = hppfs_data(); |
540 | if(data == NULL) | 501 | if (data == NULL) |
541 | goto out; | 502 | goto out; |
542 | 503 | ||
543 | proc_dentry = HPPFS_I(inode)->proc_dentry; | 504 | proc_dentry = HPPFS_I(inode)->proc_dentry; |
544 | data->proc_file = dentry_open(dget(proc_dentry), NULL, | 505 | proc_mnt = inode->i_sb->s_fs_info; |
506 | data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), | ||
545 | file_mode(file->f_mode)); | 507 | file_mode(file->f_mode)); |
546 | err = PTR_ERR(data->proc_file); | 508 | err = PTR_ERR(data->proc_file); |
547 | if(IS_ERR(data->proc_file)) | 509 | if (IS_ERR(data->proc_file)) |
548 | goto out_free; | 510 | goto out_free; |
549 | 511 | ||
550 | file->private_data = data; | 512 | file->private_data = data; |
551 | return(0); | 513 | return 0; |
552 | 514 | ||
553 | out_free: | 515 | out_free: |
554 | kfree(data); | 516 | kfree(data); |
555 | out: | 517 | out: |
556 | return(err); | 518 | return err; |
557 | } | 519 | } |
558 | 520 | ||
559 | static loff_t hppfs_llseek(struct file *file, loff_t off, int where) | 521 | static loff_t hppfs_llseek(struct file *file, loff_t off, int where) |
@@ -564,13 +526,13 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where) | |||
564 | loff_t ret; | 526 | loff_t ret; |
565 | 527 | ||
566 | llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek; | 528 | llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek; |
567 | if(llseek != NULL){ | 529 | if (llseek != NULL) { |
568 | ret = (*llseek)(proc_file, off, where); | 530 | ret = (*llseek)(proc_file, off, where); |
569 | if(ret < 0) | 531 | if (ret < 0) |
570 | return(ret); | 532 | return ret; |
571 | } | 533 | } |
572 | 534 | ||
573 | return(default_llseek(file, off, where)); | 535 | return default_llseek(file, off, where); |
574 | } | 536 | } |
575 | 537 | ||
576 | static const struct file_operations hppfs_file_fops = { | 538 | static const struct file_operations hppfs_file_fops = { |
@@ -592,11 +554,11 @@ static int hppfs_filldir(void *d, const char *name, int size, | |||
592 | { | 554 | { |
593 | struct hppfs_dirent *dirent = d; | 555 | struct hppfs_dirent *dirent = d; |
594 | 556 | ||
595 | if(file_removed(dirent->dentry, name)) | 557 | if (file_removed(dirent->dentry, name)) |
596 | return(0); | 558 | return 0; |
597 | 559 | ||
598 | return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, | 560 | return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset, |
599 | inode, type)); | 561 | inode, type); |
600 | } | 562 | } |
601 | 563 | ||
602 | static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) | 564 | static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) |
@@ -607,7 +569,8 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) | |||
607 | struct hppfs_dirent dirent = ((struct hppfs_dirent) | 569 | struct hppfs_dirent dirent = ((struct hppfs_dirent) |
608 | { .vfs_dirent = ent, | 570 | { .vfs_dirent = ent, |
609 | .filldir = filldir, | 571 | .filldir = filldir, |
610 | .dentry = file->f_path.dentry } ); | 572 | .dentry = file->f_path.dentry |
573 | }); | ||
611 | int err; | 574 | int err; |
612 | 575 | ||
613 | readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir; | 576 | readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir; |
@@ -616,12 +579,12 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) | |||
616 | err = (*readdir)(proc_file, &dirent, hppfs_filldir); | 579 | err = (*readdir)(proc_file, &dirent, hppfs_filldir); |
617 | file->f_pos = proc_file->f_pos; | 580 | file->f_pos = proc_file->f_pos; |
618 | 581 | ||
619 | return(err); | 582 | return err; |
620 | } | 583 | } |
621 | 584 | ||
622 | static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) | 585 | static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) |
623 | { | 586 | { |
624 | return(0); | 587 | return 0; |
625 | } | 588 | } |
626 | 589 | ||
627 | static const struct file_operations hppfs_dir_fops = { | 590 | static const struct file_operations hppfs_dir_fops = { |
@@ -639,7 +602,7 @@ static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf) | |||
639 | sf->f_files = 0; | 602 | sf->f_files = 0; |
640 | sf->f_ffree = 0; | 603 | sf->f_ffree = 0; |
641 | sf->f_type = HPPFS_SUPER_MAGIC; | 604 | sf->f_type = HPPFS_SUPER_MAGIC; |
642 | return(0); | 605 | return 0; |
643 | } | 606 | } |
644 | 607 | ||
645 | static struct inode *hppfs_alloc_inode(struct super_block *sb) | 608 | static struct inode *hppfs_alloc_inode(struct super_block *sb) |
@@ -647,12 +610,12 @@ static struct inode *hppfs_alloc_inode(struct super_block *sb) | |||
647 | struct hppfs_inode_info *hi; | 610 | struct hppfs_inode_info *hi; |
648 | 611 | ||
649 | hi = kmalloc(sizeof(*hi), GFP_KERNEL); | 612 | hi = kmalloc(sizeof(*hi), GFP_KERNEL); |
650 | if(hi == NULL) | 613 | if (!hi) |
651 | return(NULL); | 614 | return NULL; |
652 | 615 | ||
653 | *hi = ((struct hppfs_inode_info) { .proc_dentry = NULL }); | 616 | hi->proc_dentry = NULL; |
654 | inode_init_once(&hi->vfs_inode); | 617 | inode_init_once(&hi->vfs_inode); |
655 | return(&hi->vfs_inode); | 618 | return &hi->vfs_inode; |
656 | } | 619 | } |
657 | 620 | ||
658 | void hppfs_delete_inode(struct inode *ino) | 621 | void hppfs_delete_inode(struct inode *ino) |
@@ -665,21 +628,31 @@ static void hppfs_destroy_inode(struct inode *inode) | |||
665 | kfree(HPPFS_I(inode)); | 628 | kfree(HPPFS_I(inode)); |
666 | } | 629 | } |
667 | 630 | ||
631 | static void hppfs_put_super(struct super_block *sb) | ||
632 | { | ||
633 | mntput(sb->s_fs_info); | ||
634 | } | ||
635 | |||
668 | static const struct super_operations hppfs_sbops = { | 636 | static const struct super_operations hppfs_sbops = { |
669 | .alloc_inode = hppfs_alloc_inode, | 637 | .alloc_inode = hppfs_alloc_inode, |
670 | .destroy_inode = hppfs_destroy_inode, | 638 | .destroy_inode = hppfs_destroy_inode, |
671 | .delete_inode = hppfs_delete_inode, | 639 | .delete_inode = hppfs_delete_inode, |
672 | .statfs = hppfs_statfs, | 640 | .statfs = hppfs_statfs, |
641 | .put_super = hppfs_put_super, | ||
673 | }; | 642 | }; |
674 | 643 | ||
675 | static int hppfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 644 | static int hppfs_readlink(struct dentry *dentry, char __user *buffer, |
645 | int buflen) | ||
676 | { | 646 | { |
677 | struct file *proc_file; | 647 | struct file *proc_file; |
678 | struct dentry *proc_dentry; | 648 | struct dentry *proc_dentry; |
649 | struct vfsmount *proc_mnt; | ||
679 | int ret; | 650 | int ret; |
680 | 651 | ||
681 | proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; | 652 | proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; |
682 | proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); | 653 | proc_mnt = dentry->d_sb->s_fs_info; |
654 | |||
655 | proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); | ||
683 | if (IS_ERR(proc_file)) | 656 | if (IS_ERR(proc_file)) |
684 | return PTR_ERR(proc_file); | 657 | return PTR_ERR(proc_file); |
685 | 658 | ||
@@ -694,10 +667,13 @@ static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
694 | { | 667 | { |
695 | struct file *proc_file; | 668 | struct file *proc_file; |
696 | struct dentry *proc_dentry; | 669 | struct dentry *proc_dentry; |
670 | struct vfsmount *proc_mnt; | ||
697 | void *ret; | 671 | void *ret; |
698 | 672 | ||
699 | proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; | 673 | proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; |
700 | proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); | 674 | proc_mnt = dentry->d_sb->s_fs_info; |
675 | |||
676 | proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); | ||
701 | if (IS_ERR(proc_file)) | 677 | if (IS_ERR(proc_file)) |
702 | return proc_file; | 678 | return proc_file; |
703 | 679 | ||
@@ -717,70 +693,72 @@ static const struct inode_operations hppfs_link_iops = { | |||
717 | .follow_link = hppfs_follow_link, | 693 | .follow_link = hppfs_follow_link, |
718 | }; | 694 | }; |
719 | 695 | ||
720 | static int init_inode(struct inode *inode, struct dentry *dentry) | 696 | static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) |
721 | { | 697 | { |
722 | if(S_ISDIR(dentry->d_inode->i_mode)){ | 698 | struct inode *proc_ino = dentry->d_inode; |
699 | struct inode *inode = new_inode(sb); | ||
700 | |||
701 | if (!inode) | ||
702 | return ERR_PTR(-ENOMEM); | ||
703 | |||
704 | if (S_ISDIR(dentry->d_inode->i_mode)) { | ||
723 | inode->i_op = &hppfs_dir_iops; | 705 | inode->i_op = &hppfs_dir_iops; |
724 | inode->i_fop = &hppfs_dir_fops; | 706 | inode->i_fop = &hppfs_dir_fops; |
725 | } | 707 | } else if (S_ISLNK(dentry->d_inode->i_mode)) { |
726 | else if(S_ISLNK(dentry->d_inode->i_mode)){ | ||
727 | inode->i_op = &hppfs_link_iops; | 708 | inode->i_op = &hppfs_link_iops; |
728 | inode->i_fop = &hppfs_file_fops; | 709 | inode->i_fop = &hppfs_file_fops; |
729 | } | 710 | } else { |
730 | else { | ||
731 | inode->i_op = &hppfs_file_iops; | 711 | inode->i_op = &hppfs_file_iops; |
732 | inode->i_fop = &hppfs_file_fops; | 712 | inode->i_fop = &hppfs_file_fops; |
733 | } | 713 | } |
734 | 714 | ||
735 | HPPFS_I(inode)->proc_dentry = dentry; | 715 | HPPFS_I(inode)->proc_dentry = dentry; |
736 | 716 | ||
737 | return(0); | 717 | inode->i_uid = proc_ino->i_uid; |
718 | inode->i_gid = proc_ino->i_gid; | ||
719 | inode->i_atime = proc_ino->i_atime; | ||
720 | inode->i_mtime = proc_ino->i_mtime; | ||
721 | inode->i_ctime = proc_ino->i_ctime; | ||
722 | inode->i_ino = proc_ino->i_ino; | ||
723 | inode->i_mode = proc_ino->i_mode; | ||
724 | inode->i_nlink = proc_ino->i_nlink; | ||
725 | inode->i_size = proc_ino->i_size; | ||
726 | inode->i_blocks = proc_ino->i_blocks; | ||
727 | |||
728 | return 0; | ||
738 | } | 729 | } |
739 | 730 | ||
740 | static int hppfs_fill_super(struct super_block *sb, void *d, int silent) | 731 | static int hppfs_fill_super(struct super_block *sb, void *d, int silent) |
741 | { | 732 | { |
742 | struct inode *root_inode; | 733 | struct inode *root_inode; |
743 | struct file_system_type *procfs; | 734 | struct vfsmount *proc_mnt; |
744 | struct super_block *proc_sb; | 735 | int err = -ENOENT; |
745 | int err; | ||
746 | 736 | ||
747 | err = -ENOENT; | 737 | proc_mnt = do_kern_mount("proc", 0, "proc", NULL); |
748 | procfs = get_fs_type("proc"); | 738 | if (IS_ERR(proc_mnt)) |
749 | if(procfs == NULL) | ||
750 | goto out; | 739 | goto out; |
751 | 740 | ||
752 | if(list_empty(&procfs->fs_supers)) | ||
753 | goto out; | ||
754 | |||
755 | proc_sb = list_entry(procfs->fs_supers.next, struct super_block, | ||
756 | s_instances); | ||
757 | |||
758 | sb->s_blocksize = 1024; | 741 | sb->s_blocksize = 1024; |
759 | sb->s_blocksize_bits = 10; | 742 | sb->s_blocksize_bits = 10; |
760 | sb->s_magic = HPPFS_SUPER_MAGIC; | 743 | sb->s_magic = HPPFS_SUPER_MAGIC; |
761 | sb->s_op = &hppfs_sbops; | 744 | sb->s_op = &hppfs_sbops; |
762 | 745 | sb->s_fs_info = proc_mnt; | |
763 | root_inode = hppfs_iget(sb); | ||
764 | if (IS_ERR(root_inode)) { | ||
765 | err = PTR_ERR(root_inode); | ||
766 | goto out; | ||
767 | } | ||
768 | |||
769 | err = init_inode(root_inode, proc_sb->s_root); | ||
770 | if(err) | ||
771 | goto out_put; | ||
772 | 746 | ||
773 | err = -ENOMEM; | 747 | err = -ENOMEM; |
774 | sb->s_root = d_alloc_root(root_inode); | 748 | root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root); |
775 | if(sb->s_root == NULL) | 749 | if (!root_inode) |
776 | goto out_put; | 750 | goto out_mntput; |
777 | 751 | ||
778 | hppfs_read_inode(root_inode); | 752 | sb->s_root = d_alloc_root(root_inode); |
753 | if (!sb->s_root) | ||
754 | goto out_iput; | ||
779 | 755 | ||
780 | return(0); | 756 | return 0; |
781 | 757 | ||
782 | out_put: | 758 | out_iput: |
783 | iput(root_inode); | 759 | iput(root_inode); |
760 | out_mntput: | ||
761 | mntput(proc_mnt); | ||
784 | out: | 762 | out: |
785 | return(err); | 763 | return(err); |
786 | } | 764 | } |
@@ -802,7 +780,7 @@ static struct file_system_type hppfs_type = { | |||
802 | 780 | ||
803 | static int __init init_hppfs(void) | 781 | static int __init init_hppfs(void) |
804 | { | 782 | { |
805 | return(register_filesystem(&hppfs_type)); | 783 | return register_filesystem(&hppfs_type); |
806 | } | 784 | } |
807 | 785 | ||
808 | static void __exit exit_hppfs(void) | 786 | static void __exit exit_hppfs(void) |
@@ -813,14 +791,3 @@ static void __exit exit_hppfs(void) | |||
813 | module_init(init_hppfs) | 791 | module_init(init_hppfs) |
814 | module_exit(exit_hppfs) | 792 | module_exit(exit_hppfs) |
815 | MODULE_LICENSE("GPL"); | 793 | MODULE_LICENSE("GPL"); |
816 | |||
817 | /* | ||
818 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
819 | * Emacs will notice this stuff at the end of the file and automatically | ||
820 | * adjust the settings for this buffer only. This must remain at the end | ||
821 | * of the file. | ||
822 | * --------------------------------------------------------------------------- | ||
823 | * Local variables: | ||
824 | * c-file-style: "linux" | ||
825 | * End: | ||
826 | */ | ||
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index eee9487ae47f..6846785fe904 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -954,7 +954,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size) | |||
954 | FMODE_WRITE | FMODE_READ, | 954 | FMODE_WRITE | FMODE_READ, |
955 | &hugetlbfs_file_operations); | 955 | &hugetlbfs_file_operations); |
956 | if (!file) | 956 | if (!file) |
957 | goto out_inode; | 957 | goto out_dentry; /* inode is already attached */ |
958 | 958 | ||
959 | return file; | 959 | return file; |
960 | 960 | ||
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index 37dbd6404787..defb932eee9a 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c | |||
@@ -72,6 +72,17 @@ static int zisofs_readpage(struct file *file, struct page *page) | |||
72 | offset = index & ~zisofs_block_page_mask; | 72 | offset = index & ~zisofs_block_page_mask; |
73 | blockindex = offset >> zisofs_block_page_shift; | 73 | blockindex = offset >> zisofs_block_page_shift; |
74 | maxpage = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 74 | maxpage = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
75 | |||
76 | /* | ||
77 | * If this page is wholly outside i_size we just return zero; | ||
78 | * do_generic_file_read() will handle this for us | ||
79 | */ | ||
80 | if (page->index >= maxpage) { | ||
81 | SetPageUptodate(page); | ||
82 | unlock_page(page); | ||
83 | return 0; | ||
84 | } | ||
85 | |||
75 | maxpage = min(zisofs_block_pages, maxpage-offset); | 86 | maxpage = min(zisofs_block_pages, maxpage-offset); |
76 | 87 | ||
77 | for ( i = 0 ; i < maxpage ; i++, offset++ ) { | 88 | for ( i = 0 ; i < maxpage ; i++, offset++ ) { |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 3943a8905eb2..0e081d5f32e8 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -697,13 +697,14 @@ fail: | |||
697 | */ | 697 | */ |
698 | 698 | ||
699 | /** | 699 | /** |
700 | * journal_t * journal_init_dev() - creates an initialises a journal structure | 700 | * journal_t * journal_init_dev() - creates and initialises a journal structure |
701 | * @bdev: Block device on which to create the journal | 701 | * @bdev: Block device on which to create the journal |
702 | * @fs_dev: Device which hold journalled filesystem for this journal. | 702 | * @fs_dev: Device which hold journalled filesystem for this journal. |
703 | * @start: Block nr Start of journal. | 703 | * @start: Block nr Start of journal. |
704 | * @len: Length of the journal in blocks. | 704 | * @len: Length of the journal in blocks. |
705 | * @blocksize: blocksize of journalling device | 705 | * @blocksize: blocksize of journalling device |
706 | * @returns: a newly created journal_t * | 706 | * |
707 | * Returns: a newly created journal_t * | ||
707 | * | 708 | * |
708 | * journal_init_dev creates a journal which maps a fixed contiguous | 709 | * journal_init_dev creates a journal which maps a fixed contiguous |
709 | * range of blocks on an arbitrary block device. | 710 | * range of blocks on an arbitrary block device. |
@@ -1619,14 +1620,14 @@ static int journal_init_journal_head_cache(void) | |||
1619 | { | 1620 | { |
1620 | int retval; | 1621 | int retval; |
1621 | 1622 | ||
1622 | J_ASSERT(journal_head_cache == 0); | 1623 | J_ASSERT(journal_head_cache == NULL); |
1623 | journal_head_cache = kmem_cache_create("journal_head", | 1624 | journal_head_cache = kmem_cache_create("journal_head", |
1624 | sizeof(struct journal_head), | 1625 | sizeof(struct journal_head), |
1625 | 0, /* offset */ | 1626 | 0, /* offset */ |
1626 | SLAB_TEMPORARY, /* flags */ | 1627 | SLAB_TEMPORARY, /* flags */ |
1627 | NULL); /* ctor */ | 1628 | NULL); /* ctor */ |
1628 | retval = 0; | 1629 | retval = 0; |
1629 | if (journal_head_cache == 0) { | 1630 | if (!journal_head_cache) { |
1630 | retval = -ENOMEM; | 1631 | retval = -ENOMEM; |
1631 | printk(KERN_EMERG "JBD: no memory for journal_head cache\n"); | 1632 | printk(KERN_EMERG "JBD: no memory for journal_head cache\n"); |
1632 | } | 1633 | } |
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 2b8edf4d6eaa..43bc5e5ed064 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c | |||
@@ -478,7 +478,7 @@ static int do_one_pass(journal_t *journal, | |||
478 | memcpy(nbh->b_data, obh->b_data, | 478 | memcpy(nbh->b_data, obh->b_data, |
479 | journal->j_blocksize); | 479 | journal->j_blocksize); |
480 | if (flags & JFS_FLAG_ESCAPE) { | 480 | if (flags & JFS_FLAG_ESCAPE) { |
481 | *((__be32 *)bh->b_data) = | 481 | *((__be32 *)nbh->b_data) = |
482 | cpu_to_be32(JFS_MAGIC_NUMBER); | 482 | cpu_to_be32(JFS_MAGIC_NUMBER); |
483 | } | 483 | } |
484 | 484 | ||
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c index ad2eacf570c6..d5f8eee7c88c 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c | |||
@@ -173,13 +173,13 @@ int __init journal_init_revoke_caches(void) | |||
173 | 0, | 173 | 0, |
174 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, | 174 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, |
175 | NULL); | 175 | NULL); |
176 | if (revoke_record_cache == 0) | 176 | if (!revoke_record_cache) |
177 | return -ENOMEM; | 177 | return -ENOMEM; |
178 | 178 | ||
179 | revoke_table_cache = kmem_cache_create("revoke_table", | 179 | revoke_table_cache = kmem_cache_create("revoke_table", |
180 | sizeof(struct jbd_revoke_table_s), | 180 | sizeof(struct jbd_revoke_table_s), |
181 | 0, SLAB_TEMPORARY, NULL); | 181 | 0, SLAB_TEMPORARY, NULL); |
182 | if (revoke_table_cache == 0) { | 182 | if (!revoke_table_cache) { |
183 | kmem_cache_destroy(revoke_record_cache); | 183 | kmem_cache_destroy(revoke_record_cache); |
184 | revoke_record_cache = NULL; | 184 | revoke_record_cache = NULL; |
185 | return -ENOMEM; | 185 | return -ENOMEM; |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index c6cbb6cd59b2..2c9e8f5d13aa 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
@@ -1426,7 +1426,8 @@ int journal_stop(handle_t *handle) | |||
1426 | return err; | 1426 | return err; |
1427 | } | 1427 | } |
1428 | 1428 | ||
1429 | /**int journal_force_commit() - force any uncommitted transactions | 1429 | /** |
1430 | * int journal_force_commit() - force any uncommitted transactions | ||
1430 | * @journal: journal to force | 1431 | * @journal: journal to force |
1431 | * | 1432 | * |
1432 | * For synchronous operations: force any uncommitted transactions | 1433 | * For synchronous operations: force any uncommitted transactions |
@@ -1903,13 +1904,12 @@ zap_buffer_unlocked: | |||
1903 | } | 1904 | } |
1904 | 1905 | ||
1905 | /** | 1906 | /** |
1906 | * void journal_invalidatepage() | 1907 | * void journal_invalidatepage() - invalidate a journal page |
1907 | * @journal: journal to use for flush... | 1908 | * @journal: journal to use for flush |
1908 | * @page: page to flush | 1909 | * @page: page to flush |
1909 | * @offset: length of page to invalidate. | 1910 | * @offset: length of page to invalidate. |
1910 | * | 1911 | * |
1911 | * Reap page buffers containing data after offset in page. | 1912 | * Reap page buffers containing data after offset in page. |
1912 | * | ||
1913 | */ | 1913 | */ |
1914 | void journal_invalidatepage(journal_t *journal, | 1914 | void journal_invalidatepage(journal_t *journal, |
1915 | struct page *page, | 1915 | struct page *page, |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 96ba846992e9..954cff001df6 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -219,7 +219,7 @@ static int jbd2_journal_start_thread(journal_t *journal) | |||
219 | if (IS_ERR(t)) | 219 | if (IS_ERR(t)) |
220 | return PTR_ERR(t); | 220 | return PTR_ERR(t); |
221 | 221 | ||
222 | wait_event(journal->j_wait_done_commit, journal->j_task != 0); | 222 | wait_event(journal->j_wait_done_commit, journal->j_task != NULL); |
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | 225 | ||
@@ -231,7 +231,7 @@ static void journal_kill_thread(journal_t *journal) | |||
231 | while (journal->j_task) { | 231 | while (journal->j_task) { |
232 | wake_up(&journal->j_wait_commit); | 232 | wake_up(&journal->j_wait_commit); |
233 | spin_unlock(&journal->j_state_lock); | 233 | spin_unlock(&journal->j_state_lock); |
234 | wait_event(journal->j_wait_done_commit, journal->j_task == 0); | 234 | wait_event(journal->j_wait_done_commit, journal->j_task == NULL); |
235 | spin_lock(&journal->j_state_lock); | 235 | spin_lock(&journal->j_state_lock); |
236 | } | 236 | } |
237 | spin_unlock(&journal->j_state_lock); | 237 | spin_unlock(&journal->j_state_lock); |
@@ -1969,14 +1969,14 @@ static int journal_init_jbd2_journal_head_cache(void) | |||
1969 | { | 1969 | { |
1970 | int retval; | 1970 | int retval; |
1971 | 1971 | ||
1972 | J_ASSERT(jbd2_journal_head_cache == 0); | 1972 | J_ASSERT(jbd2_journal_head_cache == NULL); |
1973 | jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head", | 1973 | jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head", |
1974 | sizeof(struct journal_head), | 1974 | sizeof(struct journal_head), |
1975 | 0, /* offset */ | 1975 | 0, /* offset */ |
1976 | SLAB_TEMPORARY, /* flags */ | 1976 | SLAB_TEMPORARY, /* flags */ |
1977 | NULL); /* ctor */ | 1977 | NULL); /* ctor */ |
1978 | retval = 0; | 1978 | retval = 0; |
1979 | if (jbd2_journal_head_cache == 0) { | 1979 | if (!jbd2_journal_head_cache) { |
1980 | retval = -ENOMEM; | 1980 | retval = -ENOMEM; |
1981 | printk(KERN_EMERG "JBD: no memory for journal_head cache\n"); | 1981 | printk(KERN_EMERG "JBD: no memory for journal_head cache\n"); |
1982 | } | 1982 | } |
@@ -2002,14 +2002,14 @@ static struct journal_head *journal_alloc_journal_head(void) | |||
2002 | atomic_inc(&nr_journal_heads); | 2002 | atomic_inc(&nr_journal_heads); |
2003 | #endif | 2003 | #endif |
2004 | ret = kmem_cache_alloc(jbd2_journal_head_cache, GFP_NOFS); | 2004 | ret = kmem_cache_alloc(jbd2_journal_head_cache, GFP_NOFS); |
2005 | if (ret == 0) { | 2005 | if (!ret) { |
2006 | jbd_debug(1, "out of memory for journal_head\n"); | 2006 | jbd_debug(1, "out of memory for journal_head\n"); |
2007 | if (time_after(jiffies, last_warning + 5*HZ)) { | 2007 | if (time_after(jiffies, last_warning + 5*HZ)) { |
2008 | printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", | 2008 | printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", |
2009 | __FUNCTION__); | 2009 | __FUNCTION__); |
2010 | last_warning = jiffies; | 2010 | last_warning = jiffies; |
2011 | } | 2011 | } |
2012 | while (ret == 0) { | 2012 | while (!ret) { |
2013 | yield(); | 2013 | yield(); |
2014 | ret = kmem_cache_alloc(jbd2_journal_head_cache, GFP_NOFS); | 2014 | ret = kmem_cache_alloc(jbd2_journal_head_cache, GFP_NOFS); |
2015 | } | 2015 | } |
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 146411387ada..5d0405a9e7ca 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c | |||
@@ -535,7 +535,7 @@ static int do_one_pass(journal_t *journal, | |||
535 | memcpy(nbh->b_data, obh->b_data, | 535 | memcpy(nbh->b_data, obh->b_data, |
536 | journal->j_blocksize); | 536 | journal->j_blocksize); |
537 | if (flags & JBD2_FLAG_ESCAPE) { | 537 | if (flags & JBD2_FLAG_ESCAPE) { |
538 | *((__be32 *)bh->b_data) = | 538 | *((__be32 *)nbh->b_data) = |
539 | cpu_to_be32(JBD2_MAGIC_NUMBER); | 539 | cpu_to_be32(JBD2_MAGIC_NUMBER); |
540 | } | 540 | } |
541 | 541 | ||
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index df36f42e19e1..2e1453a5e998 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c | |||
@@ -174,13 +174,13 @@ int __init jbd2_journal_init_revoke_caches(void) | |||
174 | 0, | 174 | 0, |
175 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, | 175 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, |
176 | NULL); | 176 | NULL); |
177 | if (jbd2_revoke_record_cache == 0) | 177 | if (!jbd2_revoke_record_cache) |
178 | return -ENOMEM; | 178 | return -ENOMEM; |
179 | 179 | ||
180 | jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table", | 180 | jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table", |
181 | sizeof(struct jbd2_revoke_table_s), | 181 | sizeof(struct jbd2_revoke_table_s), |
182 | 0, SLAB_TEMPORARY, NULL); | 182 | 0, SLAB_TEMPORARY, NULL); |
183 | if (jbd2_revoke_table_cache == 0) { | 183 | if (!jbd2_revoke_table_cache) { |
184 | kmem_cache_destroy(jbd2_revoke_record_cache); | 184 | kmem_cache_destroy(jbd2_revoke_record_cache); |
185 | jbd2_revoke_record_cache = NULL; | 185 | jbd2_revoke_record_cache = NULL; |
186 | return -ENOMEM; | 186 | return -ENOMEM; |
diff --git a/fs/locks.c b/fs/locks.c index f36f0e61558d..d83fab1b77b5 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -1275,13 +1275,13 @@ out: | |||
1275 | EXPORT_SYMBOL(__break_lease); | 1275 | EXPORT_SYMBOL(__break_lease); |
1276 | 1276 | ||
1277 | /** | 1277 | /** |
1278 | * lease_get_mtime | 1278 | * lease_get_mtime - get the last modified time of an inode |
1279 | * @inode: the inode | 1279 | * @inode: the inode |
1280 | * @time: pointer to a timespec which will contain the last modified time | 1280 | * @time: pointer to a timespec which will contain the last modified time |
1281 | * | 1281 | * |
1282 | * This is to force NFS clients to flush their caches for files with | 1282 | * This is to force NFS clients to flush their caches for files with |
1283 | * exclusive leases. The justification is that if someone has an | 1283 | * exclusive leases. The justification is that if someone has an |
1284 | * exclusive lease, then they could be modifiying it. | 1284 | * exclusive lease, then they could be modifying it. |
1285 | */ | 1285 | */ |
1286 | void lease_get_mtime(struct inode *inode, struct timespec *time) | 1286 | void lease_get_mtime(struct inode *inode, struct timespec *time) |
1287 | { | 1287 | { |
diff --git a/fs/namei.c b/fs/namei.c index 941c8e8228c0..8cf9bb9c2fc0 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -106,7 +106,7 @@ | |||
106 | * any extra contention... | 106 | * any extra contention... |
107 | */ | 107 | */ |
108 | 108 | ||
109 | static int link_path_walk(const char *name, struct nameidata *nd); | 109 | static int __link_path_walk(const char *name, struct nameidata *nd); |
110 | 110 | ||
111 | /* In order to reduce some races, while at the same time doing additional | 111 | /* In order to reduce some races, while at the same time doing additional |
112 | * checking and hopefully speeding things up, we copy filenames to the | 112 | * checking and hopefully speeding things up, we copy filenames to the |
@@ -563,6 +563,37 @@ walk_init_root(const char *name, struct nameidata *nd) | |||
563 | return 1; | 563 | return 1; |
564 | } | 564 | } |
565 | 565 | ||
566 | /* | ||
567 | * Wrapper to retry pathname resolution whenever the underlying | ||
568 | * file system returns an ESTALE. | ||
569 | * | ||
570 | * Retry the whole path once, forcing real lookup requests | ||
571 | * instead of relying on the dcache. | ||
572 | */ | ||
573 | static __always_inline int link_path_walk(const char *name, struct nameidata *nd) | ||
574 | { | ||
575 | struct path save = nd->path; | ||
576 | int result; | ||
577 | |||
578 | /* make sure the stuff we saved doesn't go away */ | ||
579 | dget(save.dentry); | ||
580 | mntget(save.mnt); | ||
581 | |||
582 | result = __link_path_walk(name, nd); | ||
583 | if (result == -ESTALE) { | ||
584 | /* nd->path had been dropped */ | ||
585 | nd->path = save; | ||
586 | dget(nd->path.dentry); | ||
587 | mntget(nd->path.mnt); | ||
588 | nd->flags |= LOOKUP_REVAL; | ||
589 | result = __link_path_walk(name, nd); | ||
590 | } | ||
591 | |||
592 | path_put(&save); | ||
593 | |||
594 | return result; | ||
595 | } | ||
596 | |||
566 | static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) | 597 | static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) |
567 | { | 598 | { |
568 | int res = 0; | 599 | int res = 0; |
@@ -1020,36 +1051,6 @@ return_err: | |||
1020 | return err; | 1051 | return err; |
1021 | } | 1052 | } |
1022 | 1053 | ||
1023 | /* | ||
1024 | * Wrapper to retry pathname resolution whenever the underlying | ||
1025 | * file system returns an ESTALE. | ||
1026 | * | ||
1027 | * Retry the whole path once, forcing real lookup requests | ||
1028 | * instead of relying on the dcache. | ||
1029 | */ | ||
1030 | static int link_path_walk(const char *name, struct nameidata *nd) | ||
1031 | { | ||
1032 | struct nameidata save = *nd; | ||
1033 | int result; | ||
1034 | |||
1035 | /* make sure the stuff we saved doesn't go away */ | ||
1036 | dget(save.path.dentry); | ||
1037 | mntget(save.path.mnt); | ||
1038 | |||
1039 | result = __link_path_walk(name, nd); | ||
1040 | if (result == -ESTALE) { | ||
1041 | *nd = save; | ||
1042 | dget(nd->path.dentry); | ||
1043 | mntget(nd->path.mnt); | ||
1044 | nd->flags |= LOOKUP_REVAL; | ||
1045 | result = __link_path_walk(name, nd); | ||
1046 | } | ||
1047 | |||
1048 | path_put(&save.path); | ||
1049 | |||
1050 | return result; | ||
1051 | } | ||
1052 | |||
1053 | static int path_walk(const char *name, struct nameidata *nd) | 1054 | static int path_walk(const char *name, struct nameidata *nd) |
1054 | { | 1055 | { |
1055 | current->total_link_count = 0; | 1056 | current->total_link_count = 0; |
@@ -1364,13 +1365,13 @@ static int __lookup_one_len(const char *name, struct qstr *this, | |||
1364 | } | 1365 | } |
1365 | 1366 | ||
1366 | /** | 1367 | /** |
1367 | * lookup_one_len: filesystem helper to lookup single pathname component | 1368 | * lookup_one_len - filesystem helper to lookup single pathname component |
1368 | * @name: pathname component to lookup | 1369 | * @name: pathname component to lookup |
1369 | * @base: base directory to lookup from | 1370 | * @base: base directory to lookup from |
1370 | * @len: maximum length @len should be interpreted to | 1371 | * @len: maximum length @len should be interpreted to |
1371 | * | 1372 | * |
1372 | * Note that this routine is purely a helper for filesystem useage and should | 1373 | * Note that this routine is purely a helper for filesystem usage and should |
1373 | * not be called by generic code. Also note that by using this function to | 1374 | * not be called by generic code. Also note that by using this function the |
1374 | * nameidata argument is passed to the filesystem methods and a filesystem | 1375 | * nameidata argument is passed to the filesystem methods and a filesystem |
1375 | * using this helper needs to be prepared for that. | 1376 | * using this helper needs to be prepared for that. |
1376 | */ | 1377 | */ |
diff --git a/fs/namespace.c b/fs/namespace.c index 7953c96a2071..94f026ec990a 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -155,15 +155,15 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) | |||
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) | 158 | static void detach_mnt(struct vfsmount *mnt, struct path *old_path) |
159 | { | 159 | { |
160 | old_nd->path.dentry = mnt->mnt_mountpoint; | 160 | old_path->dentry = mnt->mnt_mountpoint; |
161 | old_nd->path.mnt = mnt->mnt_parent; | 161 | old_path->mnt = mnt->mnt_parent; |
162 | mnt->mnt_parent = mnt; | 162 | mnt->mnt_parent = mnt; |
163 | mnt->mnt_mountpoint = mnt->mnt_root; | 163 | mnt->mnt_mountpoint = mnt->mnt_root; |
164 | list_del_init(&mnt->mnt_child); | 164 | list_del_init(&mnt->mnt_child); |
165 | list_del_init(&mnt->mnt_hash); | 165 | list_del_init(&mnt->mnt_hash); |
166 | old_nd->path.dentry->d_mounted--; | 166 | old_path->dentry->d_mounted--; |
167 | } | 167 | } |
168 | 168 | ||
169 | void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, | 169 | void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, |
@@ -174,12 +174,12 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, | |||
174 | dentry->d_mounted++; | 174 | dentry->d_mounted++; |
175 | } | 175 | } |
176 | 176 | ||
177 | static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) | 177 | static void attach_mnt(struct vfsmount *mnt, struct path *path) |
178 | { | 178 | { |
179 | mnt_set_mountpoint(nd->path.mnt, nd->path.dentry, mnt); | 179 | mnt_set_mountpoint(path->mnt, path->dentry, mnt); |
180 | list_add_tail(&mnt->mnt_hash, mount_hashtable + | 180 | list_add_tail(&mnt->mnt_hash, mount_hashtable + |
181 | hash(nd->path.mnt, nd->path.dentry)); | 181 | hash(path->mnt, path->dentry)); |
182 | list_add_tail(&mnt->mnt_child, &nd->path.mnt->mnt_mounts); | 182 | list_add_tail(&mnt->mnt_child, &path->mnt->mnt_mounts); |
183 | } | 183 | } |
184 | 184 | ||
185 | /* | 185 | /* |
@@ -262,10 +262,8 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | |||
262 | /* stick the duplicate mount on the same expiry list | 262 | /* stick the duplicate mount on the same expiry list |
263 | * as the original if that was on one */ | 263 | * as the original if that was on one */ |
264 | if (flag & CL_EXPIRE) { | 264 | if (flag & CL_EXPIRE) { |
265 | spin_lock(&vfsmount_lock); | ||
266 | if (!list_empty(&old->mnt_expire)) | 265 | if (!list_empty(&old->mnt_expire)) |
267 | list_add(&mnt->mnt_expire, &old->mnt_expire); | 266 | list_add(&mnt->mnt_expire, &old->mnt_expire); |
268 | spin_unlock(&vfsmount_lock); | ||
269 | } | 267 | } |
270 | } | 268 | } |
271 | return mnt; | 269 | return mnt; |
@@ -548,6 +546,7 @@ void release_mounts(struct list_head *head) | |||
548 | m = mnt->mnt_parent; | 546 | m = mnt->mnt_parent; |
549 | mnt->mnt_mountpoint = mnt->mnt_root; | 547 | mnt->mnt_mountpoint = mnt->mnt_root; |
550 | mnt->mnt_parent = mnt; | 548 | mnt->mnt_parent = mnt; |
549 | m->mnt_ghosts--; | ||
551 | spin_unlock(&vfsmount_lock); | 550 | spin_unlock(&vfsmount_lock); |
552 | dput(dentry); | 551 | dput(dentry); |
553 | mntput(m); | 552 | mntput(m); |
@@ -572,12 +571,16 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) | |||
572 | __touch_mnt_namespace(p->mnt_ns); | 571 | __touch_mnt_namespace(p->mnt_ns); |
573 | p->mnt_ns = NULL; | 572 | p->mnt_ns = NULL; |
574 | list_del_init(&p->mnt_child); | 573 | list_del_init(&p->mnt_child); |
575 | if (p->mnt_parent != p) | 574 | if (p->mnt_parent != p) { |
575 | p->mnt_parent->mnt_ghosts++; | ||
576 | p->mnt_mountpoint->d_mounted--; | 576 | p->mnt_mountpoint->d_mounted--; |
577 | } | ||
577 | change_mnt_propagation(p, MS_PRIVATE); | 578 | change_mnt_propagation(p, MS_PRIVATE); |
578 | } | 579 | } |
579 | } | 580 | } |
580 | 581 | ||
582 | static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts); | ||
583 | |||
581 | static int do_umount(struct vfsmount *mnt, int flags) | 584 | static int do_umount(struct vfsmount *mnt, int flags) |
582 | { | 585 | { |
583 | struct super_block *sb = mnt->mnt_sb; | 586 | struct super_block *sb = mnt->mnt_sb; |
@@ -650,6 +653,9 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
650 | spin_lock(&vfsmount_lock); | 653 | spin_lock(&vfsmount_lock); |
651 | event++; | 654 | event++; |
652 | 655 | ||
656 | if (!(flags & MNT_DETACH)) | ||
657 | shrink_submounts(mnt, &umount_list); | ||
658 | |||
653 | retval = -EBUSY; | 659 | retval = -EBUSY; |
654 | if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { | 660 | if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { |
655 | if (!list_empty(&mnt->mnt_list)) | 661 | if (!list_empty(&mnt->mnt_list)) |
@@ -744,7 +750,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, | |||
744 | int flag) | 750 | int flag) |
745 | { | 751 | { |
746 | struct vfsmount *res, *p, *q, *r, *s; | 752 | struct vfsmount *res, *p, *q, *r, *s; |
747 | struct nameidata nd; | 753 | struct path path; |
748 | 754 | ||
749 | if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) | 755 | if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) |
750 | return NULL; | 756 | return NULL; |
@@ -769,14 +775,14 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, | |||
769 | q = q->mnt_parent; | 775 | q = q->mnt_parent; |
770 | } | 776 | } |
771 | p = s; | 777 | p = s; |
772 | nd.path.mnt = q; | 778 | path.mnt = q; |
773 | nd.path.dentry = p->mnt_mountpoint; | 779 | path.dentry = p->mnt_mountpoint; |
774 | q = clone_mnt(p, p->mnt_root, flag); | 780 | q = clone_mnt(p, p->mnt_root, flag); |
775 | if (!q) | 781 | if (!q) |
776 | goto Enomem; | 782 | goto Enomem; |
777 | spin_lock(&vfsmount_lock); | 783 | spin_lock(&vfsmount_lock); |
778 | list_add_tail(&q->mnt_list, &res->mnt_list); | 784 | list_add_tail(&q->mnt_list, &res->mnt_list); |
779 | attach_mnt(q, &nd); | 785 | attach_mnt(q, &path); |
780 | spin_unlock(&vfsmount_lock); | 786 | spin_unlock(&vfsmount_lock); |
781 | } | 787 | } |
782 | } | 788 | } |
@@ -876,11 +882,11 @@ void drop_collected_mounts(struct vfsmount *mnt) | |||
876 | * in allocations. | 882 | * in allocations. |
877 | */ | 883 | */ |
878 | static int attach_recursive_mnt(struct vfsmount *source_mnt, | 884 | static int attach_recursive_mnt(struct vfsmount *source_mnt, |
879 | struct nameidata *nd, struct nameidata *parent_nd) | 885 | struct path *path, struct path *parent_path) |
880 | { | 886 | { |
881 | LIST_HEAD(tree_list); | 887 | LIST_HEAD(tree_list); |
882 | struct vfsmount *dest_mnt = nd->path.mnt; | 888 | struct vfsmount *dest_mnt = path->mnt; |
883 | struct dentry *dest_dentry = nd->path.dentry; | 889 | struct dentry *dest_dentry = path->dentry; |
884 | struct vfsmount *child, *p; | 890 | struct vfsmount *child, *p; |
885 | 891 | ||
886 | if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) | 892 | if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) |
@@ -892,9 +898,9 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, | |||
892 | } | 898 | } |
893 | 899 | ||
894 | spin_lock(&vfsmount_lock); | 900 | spin_lock(&vfsmount_lock); |
895 | if (parent_nd) { | 901 | if (parent_path) { |
896 | detach_mnt(source_mnt, parent_nd); | 902 | detach_mnt(source_mnt, parent_path); |
897 | attach_mnt(source_mnt, nd); | 903 | attach_mnt(source_mnt, path); |
898 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 904 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
899 | } else { | 905 | } else { |
900 | mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); | 906 | mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); |
@@ -930,7 +936,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) | |||
930 | 936 | ||
931 | err = -ENOENT; | 937 | err = -ENOENT; |
932 | if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry)) | 938 | if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry)) |
933 | err = attach_recursive_mnt(mnt, nd, NULL); | 939 | err = attach_recursive_mnt(mnt, &nd->path, NULL); |
934 | out_unlock: | 940 | out_unlock: |
935 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); | 941 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); |
936 | if (!err) | 942 | if (!err) |
@@ -1059,7 +1065,8 @@ static inline int tree_contains_unbindable(struct vfsmount *mnt) | |||
1059 | */ | 1065 | */ |
1060 | static noinline int do_move_mount(struct nameidata *nd, char *old_name) | 1066 | static noinline int do_move_mount(struct nameidata *nd, char *old_name) |
1061 | { | 1067 | { |
1062 | struct nameidata old_nd, parent_nd; | 1068 | struct nameidata old_nd; |
1069 | struct path parent_path; | ||
1063 | struct vfsmount *p; | 1070 | struct vfsmount *p; |
1064 | int err = 0; | 1071 | int err = 0; |
1065 | if (!capable(CAP_SYS_ADMIN)) | 1072 | if (!capable(CAP_SYS_ADMIN)) |
@@ -1114,21 +1121,19 @@ static noinline int do_move_mount(struct nameidata *nd, char *old_name) | |||
1114 | if (p == old_nd.path.mnt) | 1121 | if (p == old_nd.path.mnt) |
1115 | goto out1; | 1122 | goto out1; |
1116 | 1123 | ||
1117 | err = attach_recursive_mnt(old_nd.path.mnt, nd, &parent_nd); | 1124 | err = attach_recursive_mnt(old_nd.path.mnt, &nd->path, &parent_path); |
1118 | if (err) | 1125 | if (err) |
1119 | goto out1; | 1126 | goto out1; |
1120 | 1127 | ||
1121 | spin_lock(&vfsmount_lock); | ||
1122 | /* if the mount is moved, it should no longer be expire | 1128 | /* if the mount is moved, it should no longer be expire |
1123 | * automatically */ | 1129 | * automatically */ |
1124 | list_del_init(&old_nd.path.mnt->mnt_expire); | 1130 | list_del_init(&old_nd.path.mnt->mnt_expire); |
1125 | spin_unlock(&vfsmount_lock); | ||
1126 | out1: | 1131 | out1: |
1127 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); | 1132 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); |
1128 | out: | 1133 | out: |
1129 | up_write(&namespace_sem); | 1134 | up_write(&namespace_sem); |
1130 | if (!err) | 1135 | if (!err) |
1131 | path_put(&parent_nd.path); | 1136 | path_put(&parent_path); |
1132 | path_put(&old_nd.path); | 1137 | path_put(&old_nd.path); |
1133 | return err; | 1138 | return err; |
1134 | } | 1139 | } |
@@ -1189,12 +1194,9 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, | |||
1189 | if ((err = graft_tree(newmnt, nd))) | 1194 | if ((err = graft_tree(newmnt, nd))) |
1190 | goto unlock; | 1195 | goto unlock; |
1191 | 1196 | ||
1192 | if (fslist) { | 1197 | if (fslist) /* add to the specified expiration list */ |
1193 | /* add to the specified expiration list */ | ||
1194 | spin_lock(&vfsmount_lock); | ||
1195 | list_add_tail(&newmnt->mnt_expire, fslist); | 1198 | list_add_tail(&newmnt->mnt_expire, fslist); |
1196 | spin_unlock(&vfsmount_lock); | 1199 | |
1197 | } | ||
1198 | up_write(&namespace_sem); | 1200 | up_write(&namespace_sem); |
1199 | return 0; | 1201 | return 0; |
1200 | 1202 | ||
@@ -1206,75 +1208,6 @@ unlock: | |||
1206 | 1208 | ||
1207 | EXPORT_SYMBOL_GPL(do_add_mount); | 1209 | EXPORT_SYMBOL_GPL(do_add_mount); |
1208 | 1210 | ||
1209 | static void expire_mount(struct vfsmount *mnt, struct list_head *mounts, | ||
1210 | struct list_head *umounts) | ||
1211 | { | ||
1212 | spin_lock(&vfsmount_lock); | ||
1213 | |||
1214 | /* | ||
1215 | * Check if mount is still attached, if not, let whoever holds it deal | ||
1216 | * with the sucker | ||
1217 | */ | ||
1218 | if (mnt->mnt_parent == mnt) { | ||
1219 | spin_unlock(&vfsmount_lock); | ||
1220 | return; | ||
1221 | } | ||
1222 | |||
1223 | /* | ||
1224 | * Check that it is still dead: the count should now be 2 - as | ||
1225 | * contributed by the vfsmount parent and the mntget above | ||
1226 | */ | ||
1227 | if (!propagate_mount_busy(mnt, 2)) { | ||
1228 | /* delete from the namespace */ | ||
1229 | touch_mnt_namespace(mnt->mnt_ns); | ||
1230 | list_del_init(&mnt->mnt_list); | ||
1231 | mnt->mnt_ns = NULL; | ||
1232 | umount_tree(mnt, 1, umounts); | ||
1233 | spin_unlock(&vfsmount_lock); | ||
1234 | } else { | ||
1235 | /* | ||
1236 | * Someone brought it back to life whilst we didn't have any | ||
1237 | * locks held so return it to the expiration list | ||
1238 | */ | ||
1239 | list_add_tail(&mnt->mnt_expire, mounts); | ||
1240 | spin_unlock(&vfsmount_lock); | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | /* | ||
1245 | * go through the vfsmounts we've just consigned to the graveyard to | ||
1246 | * - check that they're still dead | ||
1247 | * - delete the vfsmount from the appropriate namespace under lock | ||
1248 | * - dispose of the corpse | ||
1249 | */ | ||
1250 | static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts) | ||
1251 | { | ||
1252 | struct mnt_namespace *ns; | ||
1253 | struct vfsmount *mnt; | ||
1254 | |||
1255 | while (!list_empty(graveyard)) { | ||
1256 | LIST_HEAD(umounts); | ||
1257 | mnt = list_first_entry(graveyard, struct vfsmount, mnt_expire); | ||
1258 | list_del_init(&mnt->mnt_expire); | ||
1259 | |||
1260 | /* don't do anything if the namespace is dead - all the | ||
1261 | * vfsmounts from it are going away anyway */ | ||
1262 | ns = mnt->mnt_ns; | ||
1263 | if (!ns || !ns->root) | ||
1264 | continue; | ||
1265 | get_mnt_ns(ns); | ||
1266 | |||
1267 | spin_unlock(&vfsmount_lock); | ||
1268 | down_write(&namespace_sem); | ||
1269 | expire_mount(mnt, mounts, &umounts); | ||
1270 | up_write(&namespace_sem); | ||
1271 | release_mounts(&umounts); | ||
1272 | mntput(mnt); | ||
1273 | put_mnt_ns(ns); | ||
1274 | spin_lock(&vfsmount_lock); | ||
1275 | } | ||
1276 | } | ||
1277 | |||
1278 | /* | 1211 | /* |
1279 | * process a list of expirable mountpoints with the intent of discarding any | 1212 | * process a list of expirable mountpoints with the intent of discarding any |
1280 | * mountpoints that aren't in use and haven't been touched since last we came | 1213 | * mountpoints that aren't in use and haven't been touched since last we came |
@@ -1284,10 +1217,12 @@ void mark_mounts_for_expiry(struct list_head *mounts) | |||
1284 | { | 1217 | { |
1285 | struct vfsmount *mnt, *next; | 1218 | struct vfsmount *mnt, *next; |
1286 | LIST_HEAD(graveyard); | 1219 | LIST_HEAD(graveyard); |
1220 | LIST_HEAD(umounts); | ||
1287 | 1221 | ||
1288 | if (list_empty(mounts)) | 1222 | if (list_empty(mounts)) |
1289 | return; | 1223 | return; |
1290 | 1224 | ||
1225 | down_write(&namespace_sem); | ||
1291 | spin_lock(&vfsmount_lock); | 1226 | spin_lock(&vfsmount_lock); |
1292 | 1227 | ||
1293 | /* extract from the expiration list every vfsmount that matches the | 1228 | /* extract from the expiration list every vfsmount that matches the |
@@ -1298,16 +1233,19 @@ void mark_mounts_for_expiry(struct list_head *mounts) | |||
1298 | */ | 1233 | */ |
1299 | list_for_each_entry_safe(mnt, next, mounts, mnt_expire) { | 1234 | list_for_each_entry_safe(mnt, next, mounts, mnt_expire) { |
1300 | if (!xchg(&mnt->mnt_expiry_mark, 1) || | 1235 | if (!xchg(&mnt->mnt_expiry_mark, 1) || |
1301 | atomic_read(&mnt->mnt_count) != 1) | 1236 | propagate_mount_busy(mnt, 1)) |
1302 | continue; | 1237 | continue; |
1303 | |||
1304 | mntget(mnt); | ||
1305 | list_move(&mnt->mnt_expire, &graveyard); | 1238 | list_move(&mnt->mnt_expire, &graveyard); |
1306 | } | 1239 | } |
1307 | 1240 | while (!list_empty(&graveyard)) { | |
1308 | expire_mount_list(&graveyard, mounts); | 1241 | mnt = list_first_entry(&graveyard, struct vfsmount, mnt_expire); |
1309 | 1242 | touch_mnt_namespace(mnt->mnt_ns); | |
1243 | umount_tree(mnt, 1, &umounts); | ||
1244 | } | ||
1310 | spin_unlock(&vfsmount_lock); | 1245 | spin_unlock(&vfsmount_lock); |
1246 | up_write(&namespace_sem); | ||
1247 | |||
1248 | release_mounts(&umounts); | ||
1311 | } | 1249 | } |
1312 | 1250 | ||
1313 | EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); | 1251 | EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); |
@@ -1343,7 +1281,6 @@ resume: | |||
1343 | } | 1281 | } |
1344 | 1282 | ||
1345 | if (!propagate_mount_busy(mnt, 1)) { | 1283 | if (!propagate_mount_busy(mnt, 1)) { |
1346 | mntget(mnt); | ||
1347 | list_move_tail(&mnt->mnt_expire, graveyard); | 1284 | list_move_tail(&mnt->mnt_expire, graveyard); |
1348 | found++; | 1285 | found++; |
1349 | } | 1286 | } |
@@ -1363,22 +1300,22 @@ resume: | |||
1363 | * process a list of expirable mountpoints with the intent of discarding any | 1300 | * process a list of expirable mountpoints with the intent of discarding any |
1364 | * submounts of a specific parent mountpoint | 1301 | * submounts of a specific parent mountpoint |
1365 | */ | 1302 | */ |
1366 | void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts) | 1303 | static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts) |
1367 | { | 1304 | { |
1368 | LIST_HEAD(graveyard); | 1305 | LIST_HEAD(graveyard); |
1369 | int found; | 1306 | struct vfsmount *m; |
1370 | |||
1371 | spin_lock(&vfsmount_lock); | ||
1372 | 1307 | ||
1373 | /* extract submounts of 'mountpoint' from the expiration list */ | 1308 | /* extract submounts of 'mountpoint' from the expiration list */ |
1374 | while ((found = select_submounts(mountpoint, &graveyard)) != 0) | 1309 | while (select_submounts(mnt, &graveyard)) { |
1375 | expire_mount_list(&graveyard, mounts); | 1310 | while (!list_empty(&graveyard)) { |
1376 | 1311 | m = list_first_entry(&graveyard, struct vfsmount, | |
1377 | spin_unlock(&vfsmount_lock); | 1312 | mnt_expire); |
1313 | touch_mnt_namespace(mnt->mnt_ns); | ||
1314 | umount_tree(mnt, 1, umounts); | ||
1315 | } | ||
1316 | } | ||
1378 | } | 1317 | } |
1379 | 1318 | ||
1380 | EXPORT_SYMBOL_GPL(shrink_submounts); | ||
1381 | |||
1382 | /* | 1319 | /* |
1383 | * Some copy_from_user() implementations do not return the exact number of | 1320 | * Some copy_from_user() implementations do not return the exact number of |
1384 | * bytes remaining to copy on a fault. But copy_mount_options() requires that. | 1321 | * bytes remaining to copy on a fault. But copy_mount_options() requires that. |
@@ -1683,7 +1620,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path) | |||
1683 | path_put(&old_pwd); | 1620 | path_put(&old_pwd); |
1684 | } | 1621 | } |
1685 | 1622 | ||
1686 | static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) | 1623 | static void chroot_fs_refs(struct path *old_root, struct path *new_root) |
1687 | { | 1624 | { |
1688 | struct task_struct *g, *p; | 1625 | struct task_struct *g, *p; |
1689 | struct fs_struct *fs; | 1626 | struct fs_struct *fs; |
@@ -1695,12 +1632,12 @@ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) | |||
1695 | if (fs) { | 1632 | if (fs) { |
1696 | atomic_inc(&fs->count); | 1633 | atomic_inc(&fs->count); |
1697 | task_unlock(p); | 1634 | task_unlock(p); |
1698 | if (fs->root.dentry == old_nd->path.dentry | 1635 | if (fs->root.dentry == old_root->dentry |
1699 | && fs->root.mnt == old_nd->path.mnt) | 1636 | && fs->root.mnt == old_root->mnt) |
1700 | set_fs_root(fs, &new_nd->path); | 1637 | set_fs_root(fs, new_root); |
1701 | if (fs->pwd.dentry == old_nd->path.dentry | 1638 | if (fs->pwd.dentry == old_root->dentry |
1702 | && fs->pwd.mnt == old_nd->path.mnt) | 1639 | && fs->pwd.mnt == old_root->mnt) |
1703 | set_fs_pwd(fs, &new_nd->path); | 1640 | set_fs_pwd(fs, new_root); |
1704 | put_fs_struct(fs); | 1641 | put_fs_struct(fs); |
1705 | } else | 1642 | } else |
1706 | task_unlock(p); | 1643 | task_unlock(p); |
@@ -1737,7 +1674,8 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1737 | const char __user * put_old) | 1674 | const char __user * put_old) |
1738 | { | 1675 | { |
1739 | struct vfsmount *tmp; | 1676 | struct vfsmount *tmp; |
1740 | struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; | 1677 | struct nameidata new_nd, old_nd, user_nd; |
1678 | struct path parent_path, root_parent; | ||
1741 | int error; | 1679 | int error; |
1742 | 1680 | ||
1743 | if (!capable(CAP_SYS_ADMIN)) | 1681 | if (!capable(CAP_SYS_ADMIN)) |
@@ -1811,19 +1749,19 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1811 | goto out3; | 1749 | goto out3; |
1812 | } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry)) | 1750 | } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry)) |
1813 | goto out3; | 1751 | goto out3; |
1814 | detach_mnt(new_nd.path.mnt, &parent_nd); | 1752 | detach_mnt(new_nd.path.mnt, &parent_path); |
1815 | detach_mnt(user_nd.path.mnt, &root_parent); | 1753 | detach_mnt(user_nd.path.mnt, &root_parent); |
1816 | /* mount old root on put_old */ | 1754 | /* mount old root on put_old */ |
1817 | attach_mnt(user_nd.path.mnt, &old_nd); | 1755 | attach_mnt(user_nd.path.mnt, &old_nd.path); |
1818 | /* mount new_root on / */ | 1756 | /* mount new_root on / */ |
1819 | attach_mnt(new_nd.path.mnt, &root_parent); | 1757 | attach_mnt(new_nd.path.mnt, &root_parent); |
1820 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 1758 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
1821 | spin_unlock(&vfsmount_lock); | 1759 | spin_unlock(&vfsmount_lock); |
1822 | chroot_fs_refs(&user_nd, &new_nd); | 1760 | chroot_fs_refs(&user_nd.path, &new_nd.path); |
1823 | security_sb_post_pivotroot(&user_nd, &new_nd); | 1761 | security_sb_post_pivotroot(&user_nd, &new_nd); |
1824 | error = 0; | 1762 | error = 0; |
1825 | path_put(&root_parent.path); | 1763 | path_put(&root_parent); |
1826 | path_put(&parent_nd.path); | 1764 | path_put(&parent_path); |
1827 | out2: | 1765 | out2: |
1828 | mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); | 1766 | mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); |
1829 | up_write(&namespace_sem); | 1767 | up_write(&namespace_sem); |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 3d7d9631e125..5a70be589bbe 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -533,7 +533,10 @@ readpage_async_filler(void *data, struct page *page) | |||
533 | 533 | ||
534 | if (len < PAGE_CACHE_SIZE) | 534 | if (len < PAGE_CACHE_SIZE) |
535 | zero_user_segment(page, len, PAGE_CACHE_SIZE); | 535 | zero_user_segment(page, len, PAGE_CACHE_SIZE); |
536 | nfs_pageio_add_request(desc->pgio, new); | 536 | if (!nfs_pageio_add_request(desc->pgio, new)) { |
537 | error = desc->pgio->pg_error; | ||
538 | goto out_unlock; | ||
539 | } | ||
537 | return 0; | 540 | return 0; |
538 | out_error: | 541 | out_error: |
539 | error = PTR_ERR(new); | 542 | error = PTR_ERR(new); |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index dd4dfcd632ec..f9219024f31a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -589,8 +589,6 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) | |||
589 | struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); | 589 | struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); |
590 | struct rpc_clnt *rpc; | 590 | struct rpc_clnt *rpc; |
591 | 591 | ||
592 | shrink_submounts(vfsmnt, &nfs_automount_list); | ||
593 | |||
594 | if (!(flags & MNT_FORCE)) | 592 | if (!(flags & MNT_FORCE)) |
595 | return; | 593 | return; |
596 | /* -EIO all pending I/O */ | 594 | /* -EIO all pending I/O */ |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 80c61fdb2720..bed63416a55b 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -39,6 +39,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context*, | |||
39 | unsigned int, unsigned int); | 39 | unsigned int, unsigned int); |
40 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, | 40 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, |
41 | struct inode *inode, int ioflags); | 41 | struct inode *inode, int ioflags); |
42 | static void nfs_redirty_request(struct nfs_page *req); | ||
42 | static const struct rpc_call_ops nfs_write_partial_ops; | 43 | static const struct rpc_call_ops nfs_write_partial_ops; |
43 | static const struct rpc_call_ops nfs_write_full_ops; | 44 | static const struct rpc_call_ops nfs_write_full_ops; |
44 | static const struct rpc_call_ops nfs_commit_ops; | 45 | static const struct rpc_call_ops nfs_commit_ops; |
@@ -288,7 +289,12 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
288 | BUG(); | 289 | BUG(); |
289 | } | 290 | } |
290 | spin_unlock(&inode->i_lock); | 291 | spin_unlock(&inode->i_lock); |
291 | nfs_pageio_add_request(pgio, req); | 292 | if (!nfs_pageio_add_request(pgio, req)) { |
293 | nfs_redirty_request(req); | ||
294 | nfs_end_page_writeback(page); | ||
295 | nfs_clear_page_tag_locked(req); | ||
296 | return pgio->pg_error; | ||
297 | } | ||
292 | return 0; | 298 | return 0; |
293 | } | 299 | } |
294 | 300 | ||
@@ -903,6 +903,18 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) | |||
903 | int error; | 903 | int error; |
904 | struct file *f; | 904 | struct file *f; |
905 | 905 | ||
906 | /* | ||
907 | * We must always pass in a valid mount pointer. Historically | ||
908 | * callers got away with not passing it, but we must enforce this at | ||
909 | * the earliest possible point now to avoid strange problems deep in the | ||
910 | * filesystem stack. | ||
911 | */ | ||
912 | if (!mnt) { | ||
913 | printk(KERN_WARNING "%s called with NULL vfsmount\n", __func__); | ||
914 | dump_stack(); | ||
915 | return ERR_PTR(-EINVAL); | ||
916 | } | ||
917 | |||
906 | error = -ENFILE; | 918 | error = -ENFILE; |
907 | f = get_empty_filp(); | 919 | f = get_empty_filp(); |
908 | if (f == NULL) { | 920 | if (f == NULL) { |
@@ -957,13 +957,10 @@ struct file *create_write_pipe(void) | |||
957 | struct dentry *dentry; | 957 | struct dentry *dentry; |
958 | struct qstr name = { .name = "" }; | 958 | struct qstr name = { .name = "" }; |
959 | 959 | ||
960 | f = get_empty_filp(); | ||
961 | if (!f) | ||
962 | return ERR_PTR(-ENFILE); | ||
963 | err = -ENFILE; | 960 | err = -ENFILE; |
964 | inode = get_pipe_inode(); | 961 | inode = get_pipe_inode(); |
965 | if (!inode) | 962 | if (!inode) |
966 | goto err_file; | 963 | goto err; |
967 | 964 | ||
968 | err = -ENOMEM; | 965 | err = -ENOMEM; |
969 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); | 966 | dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); |
@@ -978,22 +975,24 @@ struct file *create_write_pipe(void) | |||
978 | */ | 975 | */ |
979 | dentry->d_flags &= ~DCACHE_UNHASHED; | 976 | dentry->d_flags &= ~DCACHE_UNHASHED; |
980 | d_instantiate(dentry, inode); | 977 | d_instantiate(dentry, inode); |
981 | f->f_path.mnt = mntget(pipe_mnt); | 978 | |
982 | f->f_path.dentry = dentry; | 979 | err = -ENFILE; |
980 | f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipe_fops); | ||
981 | if (!f) | ||
982 | goto err_dentry; | ||
983 | f->f_mapping = inode->i_mapping; | 983 | f->f_mapping = inode->i_mapping; |
984 | 984 | ||
985 | f->f_flags = O_WRONLY; | 985 | f->f_flags = O_WRONLY; |
986 | f->f_op = &write_pipe_fops; | ||
987 | f->f_mode = FMODE_WRITE; | ||
988 | f->f_version = 0; | 986 | f->f_version = 0; |
989 | 987 | ||
990 | return f; | 988 | return f; |
991 | 989 | ||
990 | err_dentry: | ||
991 | dput(dentry); | ||
992 | err_inode: | 992 | err_inode: |
993 | free_pipe_info(inode); | 993 | free_pipe_info(inode); |
994 | iput(inode); | 994 | iput(inode); |
995 | err_file: | 995 | err: |
996 | put_filp(f); | ||
997 | return ERR_PTR(err); | 996 | return ERR_PTR(err); |
998 | } | 997 | } |
999 | 998 | ||
diff --git a/fs/pnode.c b/fs/pnode.c index 05ba692bc540..1d8f5447f3f7 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
@@ -225,7 +225,7 @@ out: | |||
225 | */ | 225 | */ |
226 | static inline int do_refcount_check(struct vfsmount *mnt, int count) | 226 | static inline int do_refcount_check(struct vfsmount *mnt, int count) |
227 | { | 227 | { |
228 | int mycount = atomic_read(&mnt->mnt_count); | 228 | int mycount = atomic_read(&mnt->mnt_count) - mnt->mnt_ghosts; |
229 | return (mycount > count); | 229 | return (mycount > count); |
230 | } | 230 | } |
231 | 231 | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index 770de444eba0..81d7d145292a 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1036,6 +1036,26 @@ static const struct file_operations proc_loginuid_operations = { | |||
1036 | .read = proc_loginuid_read, | 1036 | .read = proc_loginuid_read, |
1037 | .write = proc_loginuid_write, | 1037 | .write = proc_loginuid_write, |
1038 | }; | 1038 | }; |
1039 | |||
1040 | static ssize_t proc_sessionid_read(struct file * file, char __user * buf, | ||
1041 | size_t count, loff_t *ppos) | ||
1042 | { | ||
1043 | struct inode * inode = file->f_path.dentry->d_inode; | ||
1044 | struct task_struct *task = get_proc_task(inode); | ||
1045 | ssize_t length; | ||
1046 | char tmpbuf[TMPBUFLEN]; | ||
1047 | |||
1048 | if (!task) | ||
1049 | return -ESRCH; | ||
1050 | length = scnprintf(tmpbuf, TMPBUFLEN, "%u", | ||
1051 | audit_get_sessionid(task)); | ||
1052 | put_task_struct(task); | ||
1053 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | ||
1054 | } | ||
1055 | |||
1056 | static const struct file_operations proc_sessionid_operations = { | ||
1057 | .read = proc_sessionid_read, | ||
1058 | }; | ||
1039 | #endif | 1059 | #endif |
1040 | 1060 | ||
1041 | #ifdef CONFIG_FAULT_INJECTION | 1061 | #ifdef CONFIG_FAULT_INJECTION |
@@ -2319,6 +2339,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2319 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2339 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2320 | #ifdef CONFIG_AUDITSYSCALL | 2340 | #ifdef CONFIG_AUDITSYSCALL |
2321 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), | 2341 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), |
2342 | REG("sessionid", S_IRUSR, sessionid), | ||
2322 | #endif | 2343 | #endif |
2323 | #ifdef CONFIG_FAULT_INJECTION | 2344 | #ifdef CONFIG_FAULT_INJECTION |
2324 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), | 2345 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), |
@@ -2649,6 +2670,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
2649 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2670 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2650 | #ifdef CONFIG_AUDITSYSCALL | 2671 | #ifdef CONFIG_AUDITSYSCALL |
2651 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), | 2672 | REG("loginuid", S_IWUSR|S_IRUGO, loginuid), |
2673 | REG("sessionid", S_IRUSR, sessionid), | ||
2652 | #endif | 2674 | #endif |
2653 | #ifdef CONFIG_FAULT_INJECTION | 2675 | #ifdef CONFIG_FAULT_INJECTION |
2654 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), | 2676 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 4206454734e0..9dfb5ff24209 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -527,13 +527,21 @@ struct pagemapread { | |||
527 | char __user *out, *end; | 527 | char __user *out, *end; |
528 | }; | 528 | }; |
529 | 529 | ||
530 | #define PM_ENTRY_BYTES sizeof(u64) | 530 | #define PM_ENTRY_BYTES sizeof(u64) |
531 | #define PM_RESERVED_BITS 3 | 531 | #define PM_STATUS_BITS 3 |
532 | #define PM_RESERVED_OFFSET (64 - PM_RESERVED_BITS) | 532 | #define PM_STATUS_OFFSET (64 - PM_STATUS_BITS) |
533 | #define PM_RESERVED_MASK (((1LL<<PM_RESERVED_BITS)-1) << PM_RESERVED_OFFSET) | 533 | #define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET) |
534 | #define PM_SPECIAL(nr) (((nr) << PM_RESERVED_OFFSET) & PM_RESERVED_MASK) | 534 | #define PM_STATUS(nr) (((nr) << PM_STATUS_OFFSET) & PM_STATUS_MASK) |
535 | #define PM_NOT_PRESENT PM_SPECIAL(1LL) | 535 | #define PM_PSHIFT_BITS 6 |
536 | #define PM_SWAP PM_SPECIAL(2LL) | 536 | #define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) |
537 | #define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) | ||
538 | #define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) | ||
539 | #define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) | ||
540 | #define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) | ||
541 | |||
542 | #define PM_PRESENT PM_STATUS(4LL) | ||
543 | #define PM_SWAP PM_STATUS(2LL) | ||
544 | #define PM_NOT_PRESENT PM_PSHIFT(PAGE_SHIFT) | ||
537 | #define PM_END_OF_BUFFER 1 | 545 | #define PM_END_OF_BUFFER 1 |
538 | 546 | ||
539 | static int add_to_pagemap(unsigned long addr, u64 pfn, | 547 | static int add_to_pagemap(unsigned long addr, u64 pfn, |
@@ -574,7 +582,7 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end, | |||
574 | u64 swap_pte_to_pagemap_entry(pte_t pte) | 582 | u64 swap_pte_to_pagemap_entry(pte_t pte) |
575 | { | 583 | { |
576 | swp_entry_t e = pte_to_swp_entry(pte); | 584 | swp_entry_t e = pte_to_swp_entry(pte); |
577 | return PM_SWAP | swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); | 585 | return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); |
578 | } | 586 | } |
579 | 587 | ||
580 | static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | 588 | static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, |
@@ -588,9 +596,11 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | |||
588 | u64 pfn = PM_NOT_PRESENT; | 596 | u64 pfn = PM_NOT_PRESENT; |
589 | pte = pte_offset_map(pmd, addr); | 597 | pte = pte_offset_map(pmd, addr); |
590 | if (is_swap_pte(*pte)) | 598 | if (is_swap_pte(*pte)) |
591 | pfn = swap_pte_to_pagemap_entry(*pte); | 599 | pfn = PM_PFRAME(swap_pte_to_pagemap_entry(*pte)) |
600 | | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP; | ||
592 | else if (pte_present(*pte)) | 601 | else if (pte_present(*pte)) |
593 | pfn = pte_pfn(*pte); | 602 | pfn = PM_PFRAME(pte_pfn(*pte)) |
603 | | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT; | ||
594 | /* unmap so we're not in atomic when we copy to userspace */ | 604 | /* unmap so we're not in atomic when we copy to userspace */ |
595 | pte_unmap(pte); | 605 | pte_unmap(pte); |
596 | err = add_to_pagemap(addr, pfn, pm); | 606 | err = add_to_pagemap(addr, pfn, pm); |
@@ -611,12 +621,20 @@ static struct mm_walk pagemap_walk = { | |||
611 | /* | 621 | /* |
612 | * /proc/pid/pagemap - an array mapping virtual pages to pfns | 622 | * /proc/pid/pagemap - an array mapping virtual pages to pfns |
613 | * | 623 | * |
614 | * For each page in the address space, this file contains one 64-bit | 624 | * For each page in the address space, this file contains one 64-bit entry |
615 | * entry representing the corresponding physical page frame number | 625 | * consisting of the following: |
616 | * (PFN) if the page is present. If there is a swap entry for the | 626 | * |
617 | * physical page, then an encoding of the swap file number and the | 627 | * Bits 0-55 page frame number (PFN) if present |
618 | * page's offset into the swap file are returned. If no page is | 628 | * Bits 0-4 swap type if swapped |
619 | * present at all, PM_NOT_PRESENT is returned. This allows determining | 629 | * Bits 5-55 swap offset if swapped |
630 | * Bits 55-60 page shift (page size = 1<<page shift) | ||
631 | * Bit 61 reserved for future use | ||
632 | * Bit 62 page swapped | ||
633 | * Bit 63 page present | ||
634 | * | ||
635 | * If the page is not present but in swap, then the PFN contains an | ||
636 | * encoding of the swap file number and the page's offset into the | ||
637 | * swap. Unmapped pages return a null PFN. This allows determining | ||
620 | * precisely which pages are mapped (or in swap) and comparing mapped | 638 | * precisely which pages are mapped (or in swap) and comparing mapped |
621 | * pages between processes. | 639 | * pages between processes. |
622 | * | 640 | * |
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index f85c5cf4934c..7ee4208793b6 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c | |||
@@ -283,7 +283,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
283 | return balance_leaf_when_delete(tb, flag); | 283 | return balance_leaf_when_delete(tb, flag); |
284 | 284 | ||
285 | zeros_num = 0; | 285 | zeros_num = 0; |
286 | if (flag == M_INSERT && body == 0) | 286 | if (flag == M_INSERT && !body) |
287 | zeros_num = ih_item_len(ih); | 287 | zeros_num = ih_item_len(ih); |
288 | 288 | ||
289 | pos_in_item = tb->tb_path->pos_in_item; | 289 | pos_in_item = tb->tb_path->pos_in_item; |
@@ -1728,7 +1728,7 @@ struct buffer_head *get_FEB(struct tree_balance *tb) | |||
1728 | struct buffer_info bi; | 1728 | struct buffer_info bi; |
1729 | 1729 | ||
1730 | for (i = 0; i < MAX_FEB_SIZE; i++) | 1730 | for (i = 0; i < MAX_FEB_SIZE; i++) |
1731 | if (tb->FEB[i] != 0) | 1731 | if (tb->FEB[i] != NULL) |
1732 | break; | 1732 | break; |
1733 | 1733 | ||
1734 | if (i == MAX_FEB_SIZE) | 1734 | if (i == MAX_FEB_SIZE) |
@@ -1827,7 +1827,7 @@ int get_left_neighbor_position(struct tree_balance *tb, int h) | |||
1827 | { | 1827 | { |
1828 | int Sh_position = PATH_H_POSITION(tb->tb_path, h + 1); | 1828 | int Sh_position = PATH_H_POSITION(tb->tb_path, h + 1); |
1829 | 1829 | ||
1830 | RFALSE(PATH_H_PPARENT(tb->tb_path, h) == 0 || tb->FL[h] == 0, | 1830 | RFALSE(PATH_H_PPARENT(tb->tb_path, h) == NULL || tb->FL[h] == NULL, |
1831 | "vs-12325: FL[%d](%p) or F[%d](%p) does not exist", | 1831 | "vs-12325: FL[%d](%p) or F[%d](%p) does not exist", |
1832 | h, tb->FL[h], h, PATH_H_PPARENT(tb->tb_path, h)); | 1832 | h, tb->FL[h], h, PATH_H_PPARENT(tb->tb_path, h)); |
1833 | 1833 | ||
@@ -1841,7 +1841,7 @@ int get_right_neighbor_position(struct tree_balance *tb, int h) | |||
1841 | { | 1841 | { |
1842 | int Sh_position = PATH_H_POSITION(tb->tb_path, h + 1); | 1842 | int Sh_position = PATH_H_POSITION(tb->tb_path, h + 1); |
1843 | 1843 | ||
1844 | RFALSE(PATH_H_PPARENT(tb->tb_path, h) == 0 || tb->FR[h] == 0, | 1844 | RFALSE(PATH_H_PPARENT(tb->tb_path, h) == NULL || tb->FR[h] == NULL, |
1845 | "vs-12330: F[%d](%p) or FR[%d](%p) does not exist", | 1845 | "vs-12330: F[%d](%p) or FR[%d](%p) does not exist", |
1846 | h, PATH_H_PPARENT(tb->tb_path, h), h, tb->FR[h]); | 1846 | h, PATH_H_PPARENT(tb->tb_path, h), h, tb->FR[h]); |
1847 | 1847 | ||
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c index 0ee35c6c9b72..07d05e0842b7 100644 --- a/fs/reiserfs/fix_node.c +++ b/fs/reiserfs/fix_node.c | |||
@@ -153,7 +153,7 @@ static void create_virtual_node(struct tree_balance *tb, int h) | |||
153 | if (vn->vn_mode == M_INSERT) { | 153 | if (vn->vn_mode == M_INSERT) { |
154 | struct virtual_item *vi = vn->vn_vi + vn->vn_affected_item_num; | 154 | struct virtual_item *vi = vn->vn_vi + vn->vn_affected_item_num; |
155 | 155 | ||
156 | RFALSE(vn->vn_ins_ih == 0, | 156 | RFALSE(vn->vn_ins_ih == NULL, |
157 | "vs-8040: item header of inserted item is not specified"); | 157 | "vs-8040: item header of inserted item is not specified"); |
158 | vi->vi_item_len = tb->insert_size[0]; | 158 | vi->vi_item_len = tb->insert_size[0]; |
159 | vi->vi_ih = vn->vn_ins_ih; | 159 | vi->vi_ih = vn->vn_ins_ih; |
@@ -857,7 +857,8 @@ static int get_lfree(struct tree_balance *tb, int h) | |||
857 | struct buffer_head *l, *f; | 857 | struct buffer_head *l, *f; |
858 | int order; | 858 | int order; |
859 | 859 | ||
860 | if ((f = PATH_H_PPARENT(tb->tb_path, h)) == 0 || (l = tb->FL[h]) == 0) | 860 | if ((f = PATH_H_PPARENT(tb->tb_path, h)) == NULL || |
861 | (l = tb->FL[h]) == NULL) | ||
861 | return 0; | 862 | return 0; |
862 | 863 | ||
863 | if (f == l) | 864 | if (f == l) |
@@ -878,7 +879,8 @@ static int get_rfree(struct tree_balance *tb, int h) | |||
878 | struct buffer_head *r, *f; | 879 | struct buffer_head *r, *f; |
879 | int order; | 880 | int order; |
880 | 881 | ||
881 | if ((f = PATH_H_PPARENT(tb->tb_path, h)) == 0 || (r = tb->FR[h]) == 0) | 882 | if ((f = PATH_H_PPARENT(tb->tb_path, h)) == NULL || |
883 | (r = tb->FR[h]) == NULL) | ||
882 | return 0; | 884 | return 0; |
883 | 885 | ||
884 | if (f == r) | 886 | if (f == r) |
diff --git a/fs/reiserfs/lbalance.c b/fs/reiserfs/lbalance.c index 281f8061ac58..6de060a6aa7f 100644 --- a/fs/reiserfs/lbalance.c +++ b/fs/reiserfs/lbalance.c | |||
@@ -626,7 +626,7 @@ static void leaf_define_dest_src_infos(int shift_mode, struct tree_balance *tb, | |||
626 | "vs-10250: leaf_define_dest_src_infos: shift type is unknown (%d)", | 626 | "vs-10250: leaf_define_dest_src_infos: shift type is unknown (%d)", |
627 | shift_mode); | 627 | shift_mode); |
628 | } | 628 | } |
629 | RFALSE(src_bi->bi_bh == 0 || dest_bi->bi_bh == 0, | 629 | RFALSE(!src_bi->bi_bh || !dest_bi->bi_bh, |
630 | "vs-10260: mode==%d, source (%p) or dest (%p) buffer is initialized incorrectly", | 630 | "vs-10260: mode==%d, source (%p) or dest (%p) buffer is initialized incorrectly", |
631 | shift_mode, src_bi->bi_bh, dest_bi->bi_bh); | 631 | shift_mode, src_bi->bi_bh, dest_bi->bi_bh); |
632 | } | 632 | } |
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index b378eea332ca..8867533cb727 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
@@ -452,7 +452,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, | |||
452 | buflen = DEH_SIZE + ROUND_UP(namelen); | 452 | buflen = DEH_SIZE + ROUND_UP(namelen); |
453 | if (buflen > sizeof(small_buf)) { | 453 | if (buflen > sizeof(small_buf)) { |
454 | buffer = kmalloc(buflen, GFP_NOFS); | 454 | buffer = kmalloc(buflen, GFP_NOFS); |
455 | if (buffer == 0) | 455 | if (!buffer) |
456 | return -ENOMEM; | 456 | return -ENOMEM; |
457 | } else | 457 | } else |
458 | buffer = small_buf; | 458 | buffer = small_buf; |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index eba037b3338f..344b9b96cc56 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -191,28 +191,11 @@ static struct dentry *get_xa_file_dentry(const struct inode *inode, | |||
191 | dput(xadir); | 191 | dput(xadir); |
192 | if (err) | 192 | if (err) |
193 | xafile = ERR_PTR(err); | 193 | xafile = ERR_PTR(err); |
194 | return xafile; | ||
195 | } | ||
196 | |||
197 | /* Opens a file pointer to the attribute associated with inode */ | ||
198 | static struct file *open_xa_file(const struct inode *inode, const char *name, | ||
199 | int flags) | ||
200 | { | ||
201 | struct dentry *xafile; | ||
202 | struct file *fp; | ||
203 | |||
204 | xafile = get_xa_file_dentry(inode, name, flags); | ||
205 | if (IS_ERR(xafile)) | ||
206 | return ERR_PTR(PTR_ERR(xafile)); | ||
207 | else if (!xafile->d_inode) { | 194 | else if (!xafile->d_inode) { |
208 | dput(xafile); | 195 | dput(xafile); |
209 | return ERR_PTR(-ENODATA); | 196 | xafile = ERR_PTR(-ENODATA); |
210 | } | 197 | } |
211 | 198 | return xafile; | |
212 | fp = dentry_open(xafile, NULL, O_RDWR); | ||
213 | /* dentry_open dputs the dentry if it fails */ | ||
214 | |||
215 | return fp; | ||
216 | } | 199 | } |
217 | 200 | ||
218 | /* | 201 | /* |
@@ -228,9 +211,8 @@ static struct file *open_xa_file(const struct inode *inode, const char *name, | |||
228 | * we're called with i_mutex held, so there are no worries about the directory | 211 | * we're called with i_mutex held, so there are no worries about the directory |
229 | * changing underneath us. | 212 | * changing underneath us. |
230 | */ | 213 | */ |
231 | static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) | 214 | static int __xattr_readdir(struct inode *inode, void *dirent, filldir_t filldir) |
232 | { | 215 | { |
233 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
234 | struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ | 216 | struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ |
235 | INITIALIZE_PATH(path_to_entry); | 217 | INITIALIZE_PATH(path_to_entry); |
236 | struct buffer_head *bh; | 218 | struct buffer_head *bh; |
@@ -374,23 +356,16 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
374 | * | 356 | * |
375 | */ | 357 | */ |
376 | static | 358 | static |
377 | int xattr_readdir(struct file *file, filldir_t filler, void *buf) | 359 | int xattr_readdir(struct inode *inode, filldir_t filler, void *buf) |
378 | { | 360 | { |
379 | struct inode *inode = file->f_path.dentry->d_inode; | 361 | int res = -ENOENT; |
380 | int res = -ENOTDIR; | ||
381 | if (!file->f_op || !file->f_op->readdir) | ||
382 | goto out; | ||
383 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); | 362 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); |
384 | // down(&inode->i_zombie); | ||
385 | res = -ENOENT; | ||
386 | if (!IS_DEADDIR(inode)) { | 363 | if (!IS_DEADDIR(inode)) { |
387 | lock_kernel(); | 364 | lock_kernel(); |
388 | res = __xattr_readdir(file, buf, filler); | 365 | res = __xattr_readdir(inode, buf, filler); |
389 | unlock_kernel(); | 366 | unlock_kernel(); |
390 | } | 367 | } |
391 | // up(&inode->i_zombie); | ||
392 | mutex_unlock(&inode->i_mutex); | 368 | mutex_unlock(&inode->i_mutex); |
393 | out: | ||
394 | return res; | 369 | return res; |
395 | } | 370 | } |
396 | 371 | ||
@@ -442,7 +417,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
442 | size_t buffer_size, int flags) | 417 | size_t buffer_size, int flags) |
443 | { | 418 | { |
444 | int err = 0; | 419 | int err = 0; |
445 | struct file *fp; | 420 | struct dentry *dentry; |
446 | struct page *page; | 421 | struct page *page; |
447 | char *data; | 422 | char *data; |
448 | struct address_space *mapping; | 423 | struct address_space *mapping; |
@@ -460,18 +435,18 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
460 | xahash = xattr_hash(buffer, buffer_size); | 435 | xahash = xattr_hash(buffer, buffer_size); |
461 | 436 | ||
462 | open_file: | 437 | open_file: |
463 | fp = open_xa_file(inode, name, flags); | 438 | dentry = get_xa_file_dentry(inode, name, flags); |
464 | if (IS_ERR(fp)) { | 439 | if (IS_ERR(dentry)) { |
465 | err = PTR_ERR(fp); | 440 | err = PTR_ERR(dentry); |
466 | goto out; | 441 | goto out; |
467 | } | 442 | } |
468 | 443 | ||
469 | xinode = fp->f_path.dentry->d_inode; | 444 | xinode = dentry->d_inode; |
470 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | 445 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; |
471 | 446 | ||
472 | /* we need to copy it off.. */ | 447 | /* we need to copy it off.. */ |
473 | if (xinode->i_nlink > 1) { | 448 | if (xinode->i_nlink > 1) { |
474 | fput(fp); | 449 | dput(dentry); |
475 | err = reiserfs_xattr_del(inode, name); | 450 | err = reiserfs_xattr_del(inode, name); |
476 | if (err < 0) | 451 | if (err < 0) |
477 | goto out; | 452 | goto out; |
@@ -485,7 +460,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
485 | newattrs.ia_size = buffer_size; | 460 | newattrs.ia_size = buffer_size; |
486 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; | 461 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; |
487 | mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR); | 462 | mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR); |
488 | err = notify_change(fp->f_path.dentry, &newattrs); | 463 | err = notify_change(dentry, &newattrs); |
489 | if (err) | 464 | if (err) |
490 | goto out_filp; | 465 | goto out_filp; |
491 | 466 | ||
@@ -518,15 +493,14 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
518 | rxh->h_hash = cpu_to_le32(xahash); | 493 | rxh->h_hash = cpu_to_le32(xahash); |
519 | } | 494 | } |
520 | 495 | ||
521 | err = reiserfs_prepare_write(fp, page, page_offset, | 496 | err = reiserfs_prepare_write(NULL, page, page_offset, |
522 | page_offset + chunk + skip); | 497 | page_offset + chunk + skip); |
523 | if (!err) { | 498 | if (!err) { |
524 | if (buffer) | 499 | if (buffer) |
525 | memcpy(data + skip, buffer + buffer_pos, chunk); | 500 | memcpy(data + skip, buffer + buffer_pos, chunk); |
526 | err = | 501 | err = reiserfs_commit_write(NULL, page, page_offset, |
527 | reiserfs_commit_write(fp, page, page_offset, | 502 | page_offset + chunk + |
528 | page_offset + chunk + | 503 | skip); |
529 | skip); | ||
530 | } | 504 | } |
531 | unlock_page(page); | 505 | unlock_page(page); |
532 | reiserfs_put_page(page); | 506 | reiserfs_put_page(page); |
@@ -548,7 +522,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
548 | 522 | ||
549 | out_filp: | 523 | out_filp: |
550 | mutex_unlock(&xinode->i_mutex); | 524 | mutex_unlock(&xinode->i_mutex); |
551 | fput(fp); | 525 | dput(dentry); |
552 | 526 | ||
553 | out: | 527 | out: |
554 | return err; | 528 | return err; |
@@ -562,7 +536,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
562 | size_t buffer_size) | 536 | size_t buffer_size) |
563 | { | 537 | { |
564 | ssize_t err = 0; | 538 | ssize_t err = 0; |
565 | struct file *fp; | 539 | struct dentry *dentry; |
566 | size_t isize; | 540 | size_t isize; |
567 | size_t file_pos = 0; | 541 | size_t file_pos = 0; |
568 | size_t buffer_pos = 0; | 542 | size_t buffer_pos = 0; |
@@ -578,13 +552,13 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
578 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | 552 | if (get_inode_sd_version(inode) == STAT_DATA_V1) |
579 | return -EOPNOTSUPP; | 553 | return -EOPNOTSUPP; |
580 | 554 | ||
581 | fp = open_xa_file(inode, name, FL_READONLY); | 555 | dentry = get_xa_file_dentry(inode, name, FL_READONLY); |
582 | if (IS_ERR(fp)) { | 556 | if (IS_ERR(dentry)) { |
583 | err = PTR_ERR(fp); | 557 | err = PTR_ERR(dentry); |
584 | goto out; | 558 | goto out; |
585 | } | 559 | } |
586 | 560 | ||
587 | xinode = fp->f_path.dentry->d_inode; | 561 | xinode = dentry->d_inode; |
588 | isize = xinode->i_size; | 562 | isize = xinode->i_size; |
589 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | 563 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; |
590 | 564 | ||
@@ -652,7 +626,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
652 | } | 626 | } |
653 | 627 | ||
654 | out_dput: | 628 | out_dput: |
655 | fput(fp); | 629 | dput(dentry); |
656 | 630 | ||
657 | out: | 631 | out: |
658 | return err; | 632 | return err; |
@@ -742,7 +716,6 @@ reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen, | |||
742 | /* This is called w/ inode->i_mutex downed */ | 716 | /* This is called w/ inode->i_mutex downed */ |
743 | int reiserfs_delete_xattrs(struct inode *inode) | 717 | int reiserfs_delete_xattrs(struct inode *inode) |
744 | { | 718 | { |
745 | struct file *fp; | ||
746 | struct dentry *dir, *root; | 719 | struct dentry *dir, *root; |
747 | int err = 0; | 720 | int err = 0; |
748 | 721 | ||
@@ -763,15 +736,8 @@ int reiserfs_delete_xattrs(struct inode *inode) | |||
763 | return 0; | 736 | return 0; |
764 | } | 737 | } |
765 | 738 | ||
766 | fp = dentry_open(dir, NULL, O_RDWR); | ||
767 | if (IS_ERR(fp)) { | ||
768 | err = PTR_ERR(fp); | ||
769 | /* dentry_open dputs the dentry if it fails */ | ||
770 | goto out; | ||
771 | } | ||
772 | |||
773 | lock_kernel(); | 739 | lock_kernel(); |
774 | err = xattr_readdir(fp, reiserfs_delete_xattrs_filler, dir); | 740 | err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir); |
775 | if (err) { | 741 | if (err) { |
776 | unlock_kernel(); | 742 | unlock_kernel(); |
777 | goto out_dir; | 743 | goto out_dir; |
@@ -791,7 +757,7 @@ int reiserfs_delete_xattrs(struct inode *inode) | |||
791 | unlock_kernel(); | 757 | unlock_kernel(); |
792 | 758 | ||
793 | out_dir: | 759 | out_dir: |
794 | fput(fp); | 760 | dput(dir); |
795 | 761 | ||
796 | out: | 762 | out: |
797 | if (!err) | 763 | if (!err) |
@@ -833,7 +799,6 @@ reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen, | |||
833 | 799 | ||
834 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | 800 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) |
835 | { | 801 | { |
836 | struct file *fp; | ||
837 | struct dentry *dir; | 802 | struct dentry *dir; |
838 | int err = 0; | 803 | int err = 0; |
839 | struct reiserfs_chown_buf buf; | 804 | struct reiserfs_chown_buf buf; |
@@ -857,13 +822,6 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | |||
857 | goto out; | 822 | goto out; |
858 | } | 823 | } |
859 | 824 | ||
860 | fp = dentry_open(dir, NULL, O_RDWR); | ||
861 | if (IS_ERR(fp)) { | ||
862 | err = PTR_ERR(fp); | ||
863 | /* dentry_open dputs the dentry if it fails */ | ||
864 | goto out; | ||
865 | } | ||
866 | |||
867 | lock_kernel(); | 825 | lock_kernel(); |
868 | 826 | ||
869 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); | 827 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); |
@@ -871,7 +829,7 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | |||
871 | buf.attrs = attrs; | 829 | buf.attrs = attrs; |
872 | buf.inode = inode; | 830 | buf.inode = inode; |
873 | 831 | ||
874 | err = xattr_readdir(fp, reiserfs_chown_xattrs_filler, &buf); | 832 | err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf); |
875 | if (err) { | 833 | if (err) { |
876 | unlock_kernel(); | 834 | unlock_kernel(); |
877 | goto out_dir; | 835 | goto out_dir; |
@@ -881,7 +839,7 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | |||
881 | unlock_kernel(); | 839 | unlock_kernel(); |
882 | 840 | ||
883 | out_dir: | 841 | out_dir: |
884 | fput(fp); | 842 | dput(dir); |
885 | 843 | ||
886 | out: | 844 | out: |
887 | attrs->ia_valid = ia_valid; | 845 | attrs->ia_valid = ia_valid; |
@@ -1029,7 +987,6 @@ reiserfs_listxattr_filler(void *buf, const char *name, int namelen, | |||
1029 | */ | 987 | */ |
1030 | ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | 988 | ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) |
1031 | { | 989 | { |
1032 | struct file *fp; | ||
1033 | struct dentry *dir; | 990 | struct dentry *dir; |
1034 | int err = 0; | 991 | int err = 0; |
1035 | struct reiserfs_listxattr_buf buf; | 992 | struct reiserfs_listxattr_buf buf; |
@@ -1052,13 +1009,6 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
1052 | goto out; | 1009 | goto out; |
1053 | } | 1010 | } |
1054 | 1011 | ||
1055 | fp = dentry_open(dir, NULL, O_RDWR); | ||
1056 | if (IS_ERR(fp)) { | ||
1057 | err = PTR_ERR(fp); | ||
1058 | /* dentry_open dputs the dentry if it fails */ | ||
1059 | goto out; | ||
1060 | } | ||
1061 | |||
1062 | buf.r_buf = buffer; | 1012 | buf.r_buf = buffer; |
1063 | buf.r_size = buffer ? size : 0; | 1013 | buf.r_size = buffer ? size : 0; |
1064 | buf.r_pos = 0; | 1014 | buf.r_pos = 0; |
@@ -1066,7 +1016,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
1066 | 1016 | ||
1067 | REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir; | 1017 | REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir; |
1068 | 1018 | ||
1069 | err = xattr_readdir(fp, reiserfs_listxattr_filler, &buf); | 1019 | err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf); |
1070 | if (err) | 1020 | if (err) |
1071 | goto out_dir; | 1021 | goto out_dir; |
1072 | 1022 | ||
@@ -1076,7 +1026,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | |||
1076 | err = buf.r_pos; | 1026 | err = buf.r_pos; |
1077 | 1027 | ||
1078 | out_dir: | 1028 | out_dir: |
1079 | fput(fp); | 1029 | dput(dir); |
1080 | 1030 | ||
1081 | out: | 1031 | out: |
1082 | reiserfs_read_unlock_xattr_i(dentry->d_inode); | 1032 | reiserfs_read_unlock_xattr_i(dentry->d_inode); |
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 00b6f0a518c8..3f13d491c7c7 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c | |||
@@ -340,8 +340,9 @@ static struct dentry * | |||
340 | romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 340 | romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
341 | { | 341 | { |
342 | unsigned long offset, maxoff; | 342 | unsigned long offset, maxoff; |
343 | int fslen, res; | 343 | long res; |
344 | struct inode *inode; | 344 | int fslen; |
345 | struct inode *inode = NULL; | ||
345 | char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ | 346 | char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ |
346 | struct romfs_inode ri; | 347 | struct romfs_inode ri; |
347 | const char *name; /* got from dentry */ | 348 | const char *name; /* got from dentry */ |
@@ -351,7 +352,7 @@ romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
351 | offset = dir->i_ino & ROMFH_MASK; | 352 | offset = dir->i_ino & ROMFH_MASK; |
352 | lock_kernel(); | 353 | lock_kernel(); |
353 | if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) | 354 | if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) |
354 | goto out; | 355 | goto error; |
355 | 356 | ||
356 | maxoff = romfs_maxsize(dir->i_sb); | 357 | maxoff = romfs_maxsize(dir->i_sb); |
357 | offset = be32_to_cpu(ri.spec) & ROMFH_MASK; | 358 | offset = be32_to_cpu(ri.spec) & ROMFH_MASK; |
@@ -364,9 +365,9 @@ romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
364 | 365 | ||
365 | for(;;) { | 366 | for(;;) { |
366 | if (!offset || offset >= maxoff) | 367 | if (!offset || offset >= maxoff) |
367 | goto out0; | 368 | goto success; /* negative success */ |
368 | if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) | 369 | if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) |
369 | goto out; | 370 | goto error; |
370 | 371 | ||
371 | /* try to match the first 16 bytes of name */ | 372 | /* try to match the first 16 bytes of name */ |
372 | fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE); | 373 | fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE); |
@@ -397,23 +398,14 @@ romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
397 | inode = romfs_iget(dir->i_sb, offset); | 398 | inode = romfs_iget(dir->i_sb, offset); |
398 | if (IS_ERR(inode)) { | 399 | if (IS_ERR(inode)) { |
399 | res = PTR_ERR(inode); | 400 | res = PTR_ERR(inode); |
400 | goto out; | 401 | goto error; |
401 | } | 402 | } |
402 | 403 | ||
403 | /* | 404 | success: |
404 | * it's a bit funky, _lookup needs to return an error code | 405 | d_add(dentry, inode); |
405 | * (negative) or a NULL, both as a dentry. ENOENT should not | ||
406 | * be returned, instead we need to create a negative dentry by | ||
407 | * d_add(dentry, NULL); and return 0 as no error. | ||
408 | * (Although as I see, it only matters on writable file | ||
409 | * systems). | ||
410 | */ | ||
411 | |||
412 | out0: inode = NULL; | ||
413 | res = 0; | 406 | res = 0; |
414 | d_add (dentry, inode); | 407 | error: |
415 | 408 | unlock_kernel(); | |
416 | out: unlock_kernel(); | ||
417 | return ERR_PTR(res); | 409 | return ERR_PTR(res); |
418 | } | 410 | } |
419 | 411 | ||
diff --git a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c index fae8e85af0ed..6bd9b691a463 100644 --- a/fs/smbfs/smbiod.c +++ b/fs/smbfs/smbiod.c | |||
@@ -206,7 +206,7 @@ int smbiod_retry(struct smb_sb_info *server) | |||
206 | 206 | ||
207 | smb_close_socket(server); | 207 | smb_close_socket(server); |
208 | 208 | ||
209 | if (pid == 0) { | 209 | if (!pid) { |
210 | /* FIXME: this is fatal, umount? */ | 210 | /* FIXME: this is fatal, umount? */ |
211 | printk(KERN_ERR "smb_retry: no connection process\n"); | 211 | printk(KERN_ERR "smb_retry: no connection process\n"); |
212 | server->state = CONN_RETRIED; | 212 | server->state = CONN_RETRIED; |
diff --git a/fs/super.c b/fs/super.c index 010446d8c40a..09008dbd264e 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -556,11 +556,11 @@ out: | |||
556 | } | 556 | } |
557 | 557 | ||
558 | /** | 558 | /** |
559 | * mark_files_ro | 559 | * mark_files_ro - mark all files read-only |
560 | * @sb: superblock in question | 560 | * @sb: superblock in question |
561 | * | 561 | * |
562 | * All files are marked read/only. We don't care about pending | 562 | * All files are marked read-only. We don't care about pending |
563 | * delete files so this should be used in 'force' mode only | 563 | * delete files so this should be used in 'force' mode only. |
564 | */ | 564 | */ |
565 | 565 | ||
566 | static void mark_files_ro(struct super_block *sb) | 566 | static void mark_files_ro(struct super_block *sb) |
@@ -945,6 +945,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) | |||
945 | put_filesystem(type); | 945 | put_filesystem(type); |
946 | return mnt; | 946 | return mnt; |
947 | } | 947 | } |
948 | EXPORT_SYMBOL_GPL(do_kern_mount); | ||
948 | 949 | ||
949 | struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) | 950 | struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) |
950 | { | 951 | { |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index a271c87c4472..baa663e69388 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/kobject.h> | 14 | #include <linux/kobject.h> |
15 | #include <linux/kallsyms.h> | ||
15 | #include <linux/namei.h> | 16 | #include <linux/namei.h> |
16 | #include <linux/poll.h> | 17 | #include <linux/poll.h> |
17 | #include <linux/list.h> | 18 | #include <linux/list.h> |
@@ -86,7 +87,12 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer | |||
86 | * The code works fine with PAGE_SIZE return but it's likely to | 87 | * The code works fine with PAGE_SIZE return but it's likely to |
87 | * indicate truncated result or overflow in normal use cases. | 88 | * indicate truncated result or overflow in normal use cases. |
88 | */ | 89 | */ |
89 | BUG_ON(count >= (ssize_t)PAGE_SIZE); | 90 | if (count >= (ssize_t)PAGE_SIZE) { |
91 | print_symbol("fill_read_buffer: %s returned bad count\n", | ||
92 | (unsigned long)ops->show); | ||
93 | /* Try to struggle along */ | ||
94 | count = PAGE_SIZE - 1; | ||
95 | } | ||
90 | if (count >= 0) { | 96 | if (count >= 0) { |
91 | buffer->needs_read_fill = 0; | 97 | buffer->needs_read_fill = 0; |
92 | buffer->count = count; | 98 | buffer->count = count; |
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 1fca381f0ce2..1e7598fb9787 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
@@ -315,8 +315,8 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg, | |||
315 | } | 315 | } |
316 | 316 | ||
317 | UFSD(" change from %llu to %llu, pos %u\n", | 317 | UFSD(" change from %llu to %llu, pos %u\n", |
318 | (unsigned long long)pos + oldb, | 318 | (unsigned long long)(pos + oldb), |
319 | (unsigned long long)pos + newb, pos); | 319 | (unsigned long long)(pos + newb), pos); |
320 | 320 | ||
321 | bh->b_blocknr = newb + pos; | 321 | bh->b_blocknr = newb + pos; |
322 | unmap_underlying_metadata(bh->b_bdev, | 322 | unmap_underlying_metadata(bh->b_bdev, |