]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Goldwyn Rodrigues <rgoldwyn@suse.de> |
2 | Subject: Unlink mapped drives on exit | |
3 | References: bnc#449451 | |
4 | ||
5 | Mapped drives were not being unlinked properly because | |
6 | of ABI change in the kernel. Fixed local_unlink function | |
7 | to correctly unlink files. | |
8 | ||
9 | --- | |
10 | fs/novfs/daemon.c | 97 +++++++++++++++++++++++++++++++----------------------- | |
11 | fs/novfs/nwcapi.c | 2 - | |
12 | 2 files changed, 57 insertions(+), 42 deletions(-) | |
13 | ||
14 | Index: linux-2.6.27/fs/novfs/daemon.c | |
15 | =================================================================== | |
16 | --- linux-2.6.27.orig/fs/novfs/daemon.c 2008-11-27 16:02:22.000000000 +0530 | |
17 | +++ linux-2.6.27/fs/novfs/daemon.c 2008-11-28 11:20:08.000000000 +0530 | |
18 | @@ -15,6 +15,7 @@ | |
19 | ||
20 | #include <linux/module.h> | |
21 | #include <linux/fs.h> | |
22 | +#include <linux/mount.h> | |
23 | #include <linux/slab.h> | |
24 | #include <linux/list.h> | |
25 | #include <linux/timer.h> | |
26 | @@ -96,7 +97,7 @@ static int NwdConvertNetwareHandle(struc | |
27 | static int set_map_drive(struct novfs_xplat *pdata, struct novfs_schandle Session); | |
28 | static int unmap_drive(struct novfs_xplat *pdata, struct novfs_schandle Session); | |
29 | static int NwdGetMountPath(struct novfs_xplat *pdata); | |
30 | -static int local_unlink(const char *pathname); | |
31 | +static long local_unlink(const char *pathname); | |
32 | ||
33 | ||
34 | /*===[ Global variables ]=================================================*/ | |
35 | @@ -1610,7 +1611,7 @@ int novfs_daemon_lib_ioctl(struct inode | |
36 | ||
37 | case NWC_SET_CONN_INFO: | |
38 | DbgPrint | |
39 | - ("[VFS XPLAT] Call NwGetConnInfo\n"); | |
40 | + ("[VFS XPLAT] Call NwSetConnInfo\n"); | |
41 | retCode = | |
42 | novfs_set_conn_info(&data, dh->session); | |
43 | break; | |
44 | @@ -2061,54 +2062,68 @@ static void RemoveDriveMaps(void) | |
45 | up(&DriveMapLock); | |
46 | } | |
47 | ||
48 | -static int local_unlink(const char *pathname) | |
49 | +/* As picked from do_unlinkat() */ | |
50 | + | |
51 | +static long local_unlink(const char *pathname) | |
52 | { | |
53 | int error; | |
54 | struct dentry *dentry; | |
55 | + char *name, *c; | |
56 | struct nameidata nd; | |
57 | struct inode *inode = NULL; | |
58 | ||
59 | - DbgPrint("local_unlink: %s\n", pathname); | |
60 | error = path_lookup(pathname, LOOKUP_PARENT, &nd); | |
61 | - DbgPrint("local_unlink: path_lookup %d\n", error); | |
62 | - if (!error) { | |
63 | - error = -EISDIR; | |
64 | - if (nd.last_type == LAST_NORM) { | |
65 | - dentry = lookup_create(&nd, 1); | |
66 | - DbgPrint("local_unlink: lookup_hash 0x%p\n", dentry); | |
67 | - | |
68 | - error = PTR_ERR(dentry); | |
69 | - if (!IS_ERR(dentry)) { | |
70 | - if (nd.last.name[nd.last.len]) { | |
71 | - error = | |
72 | - !dentry-> | |
73 | - d_inode ? -ENOENT : S_ISDIR(dentry-> | |
74 | - d_inode-> | |
75 | - i_mode) | |
76 | - ? -EISDIR : -ENOTDIR; | |
77 | - } else { | |
78 | - inode = dentry->d_inode; | |
79 | - if (inode) { | |
80 | - atomic_inc(&inode->i_count); | |
81 | - } | |
82 | - error = vfs_unlink(nd.path.dentry->d_inode, dentry, nd.path.mnt); | |
83 | - DbgPrint | |
84 | - ("local_unlink: vfs_unlink %d\n", | |
85 | - error); | |
86 | - } | |
87 | - dput(dentry); | |
88 | - } | |
89 | - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
90 | - | |
91 | - } | |
92 | - path_put(&nd.path); | |
93 | + DbgPrint("local_unlink: path_lookup %s error: %d\n", pathname, error); | |
94 | + if (error) | |
95 | + return error; | |
96 | + | |
97 | + error = -EISDIR; | |
98 | + if (nd.last_type != LAST_NORM) | |
99 | + goto exit1; | |
100 | + mutex_lock(&nd.path.dentry->d_inode->i_mutex); | |
101 | + /* Get the filename of pathname */ | |
102 | + name=c=(char *)pathname; | |
103 | + while (*c!='\0') { | |
104 | + if (*c=='/') | |
105 | + name=++c; | |
106 | + c++; | |
107 | + } | |
108 | + dentry = lookup_one_len(name, nd.path.dentry, strlen(name)); | |
109 | + error = PTR_ERR(dentry); | |
110 | + DbgPrint("local_unlink: dentry %p\n", dentry); | |
111 | + if (!(dentry->d_inode->i_mode & S_IFLNK)) { | |
112 | + DbgPrint("local_unlink: %s not a link", name); | |
113 | + error=-ENOENT; | |
114 | + goto exit1; | |
115 | + } | |
116 | + | |
117 | + if (!IS_ERR(dentry)) { | |
118 | + /* Why not before? Because we want correct error value */ | |
119 | + if (nd.last.name[nd.last.len]) | |
120 | + goto slashes; | |
121 | + inode = dentry->d_inode; | |
122 | + if (inode) | |
123 | + atomic_inc(&inode->i_count); | |
124 | + error = mnt_want_write(nd.path.mnt); | |
125 | + DbgPrint("local_unlink: inode %p mnt_want_write error %d\n", inode, error); | |
126 | + if (error) | |
127 | + goto exit2; | |
128 | + error = vfs_unlink(nd.path.dentry->d_inode, dentry, nd.path.mnt); | |
129 | + mnt_drop_write(nd.path.mnt); | |
130 | + exit2: | |
131 | + dput(dentry); | |
132 | } | |
133 | - | |
134 | - if (inode) { | |
135 | + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
136 | + if (inode) | |
137 | iput(inode); /* truncate the inode here */ | |
138 | - } | |
139 | - | |
140 | - DbgPrint("local_unlink: error=%d\n", error); | |
141 | +exit1: | |
142 | + path_put(&nd.path); | |
143 | + DbgPrint("local_unlink: returning error %d\n", error); | |
144 | return error; | |
145 | + | |
146 | +slashes: | |
147 | + error = !dentry->d_inode ? -ENOENT : | |
148 | + S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; | |
149 | + goto exit2; | |
150 | } | |
151 | ||
152 | Index: linux-2.6.27/fs/novfs/nwcapi.c | |
153 | =================================================================== | |
154 | --- linux-2.6.27.orig/fs/novfs/nwcapi.c 2008-11-27 16:02:22.000000000 +0530 | |
155 | +++ linux-2.6.27/fs/novfs/nwcapi.c 2008-11-28 11:02:15.000000000 +0530 | |
156 | @@ -993,7 +993,7 @@ int novfs_scan_conn_info(struct novfs_xp | |
157 | DbgPrint("NwScanConnInfo: Reply recieved\n"); | |
158 | DbgPrint(" NextIndex = %x\n", connInfo.uScanIndex); | |
159 | DbgPrint(" ErrorCode = %x\n", reply->Reply.ErrorCode); | |
160 | - DbgPrint(" data = %x\n", reply->data); | |
161 | + DbgPrint(" data = %p\n", reply->data); | |
162 | ||
163 | pDConnInfo = (struct nwd_scan_conn_info *) reply->data; | |
164 | retCode = (unsigned long) reply->Reply.ErrorCode; |