aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSachin Prabhu <sprabhu@redhat.com>2013-11-25 12:09:52 -0500
committerSteve French <smfrench@gmail.com>2014-01-20 01:14:00 -0500
commitcbb0aba6ff3ff5b64f094f81f4d99d2323c0afcc (patch)
treeea11e115ecfc85225e7abda30ccf75db5996f3cf
parent8205d1bb31af047c6893a4f9e86ed88cf5d6113d (diff)
cifs: Add create MFSymlinks to protocol ops struct
Add a new protocol ops function create_mf_symlink and have create_mf_symlink() use it. This patchset moves the MFSymlink operations completely to the ops structure so that we only use the right protocol versions when querying or creating MFSymlinks. Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/link.c88
-rw-r--r--fs/cifs/smb1ops.c1
4 files changed, 54 insertions, 42 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index fba4d1341f88..61228b7f6b67 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -373,6 +373,9 @@ struct smb_version_operations {
373 int (*query_mf_symlink)(unsigned int, struct cifs_tcon *, 373 int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
374 struct cifs_sb_info *, const unsigned char *, 374 struct cifs_sb_info *, const unsigned char *,
375 char *, unsigned int *); 375 char *, unsigned int *);
376 int (*create_mf_symlink)(unsigned int, struct cifs_tcon *,
377 struct cifs_sb_info *, const unsigned char *,
378 char *, unsigned int *);
376 /* if we can do cache read operations */ 379 /* if we can do cache read operations */
377 bool (*is_read_op)(__u32); 380 bool (*is_read_op)(__u32);
378 /* set oplock level for the inode */ 381 /* set oplock level for the inode */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 78bb6d6ad06a..e88c3b192ef5 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -500,4 +500,8 @@ int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
500 struct cifs_sb_info *cifs_sb, 500 struct cifs_sb_info *cifs_sb,
501 const unsigned char *path, char *pbuf, 501 const unsigned char *path, char *pbuf,
502 unsigned int *pbytes_read); 502 unsigned int *pbytes_read);
503int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
504 struct cifs_sb_info *cifs_sb,
505 const unsigned char *path, char *pbuf,
506 unsigned int *pbytes_written);
503#endif /* _CIFSPROTO_H */ 507#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 77dbd55795d8..3f259aad361d 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -180,59 +180,31 @@ format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
180 180
181static int 181static int
182create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, 182create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
183 const char *fromName, const char *toName, 183 struct cifs_sb_info *cifs_sb, const char *fromName,
184 struct cifs_sb_info *cifs_sb) 184 const char *toName)
185{ 185{
186 int rc; 186 int rc;
187 int oplock = 0;
188 int remap;
189 int create_options = CREATE_NOT_DIR;
190 __u16 netfid = 0;
191 u8 *buf; 187 u8 *buf;
192 unsigned int bytes_written = 0; 188 unsigned int bytes_written = 0;
193 struct cifs_io_parms io_parms;
194 struct nls_table *nls_codepage;
195
196 nls_codepage = cifs_sb->local_nls;
197 remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
198 189
199 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); 190 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
200 if (!buf) 191 if (!buf)
201 return -ENOMEM; 192 return -ENOMEM;
202 193
203 rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); 194 rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
204 if (rc != 0) { 195 if (rc)
205 kfree(buf); 196 goto out;
206 return rc;
207 }
208
209 if (backup_cred(cifs_sb))
210 create_options |= CREATE_OPEN_BACKUP_INTENT;
211
212 rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
213 create_options, &netfid, &oplock, NULL,
214 nls_codepage, remap);
215 if (rc != 0) {
216 kfree(buf);
217 return rc;
218 }
219
220 io_parms.netfid = netfid;
221 io_parms.pid = current->tgid;
222 io_parms.tcon = tcon;
223 io_parms.offset = 0;
224 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
225 197
226 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0); 198 rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb,
227 CIFSSMBClose(xid, tcon, netfid); 199 fromName, buf, &bytes_written);
228 kfree(buf); 200 if (rc)
229 if (rc != 0) 201 goto out;
230 return rc;
231 202
232 if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) 203 if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
233 return -EIO; 204 rc = -EIO;
234 205out:
235 return 0; 206 kfree(buf);
207 return rc;
236} 208}
237 209
238static int 210static int
@@ -320,6 +292,39 @@ out:
320} 292}
321 293
322int 294int
295cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
296 struct cifs_sb_info *cifs_sb, const unsigned char *path,
297 char *pbuf, unsigned int *pbytes_written)
298{
299 int rc;
300 int oplock = 0;
301 __u16 netfid = 0;
302 struct cifs_io_parms io_parms;
303 int create_options = CREATE_NOT_DIR;
304
305 if (backup_cred(cifs_sb))
306 create_options |= CREATE_OPEN_BACKUP_INTENT;
307
308 rc = CIFSSMBOpen(xid, tcon, path, FILE_CREATE, GENERIC_WRITE,
309 create_options, &netfid, &oplock, NULL,
310 cifs_sb->local_nls,
311 cifs_sb->mnt_cifs_flags &
312 CIFS_MOUNT_MAP_SPECIAL_CHR);
313 if (rc)
314 return rc;
315
316 io_parms.netfid = netfid;
317 io_parms.pid = current->tgid;
318 io_parms.tcon = tcon;
319 io_parms.offset = 0;
320 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
321
322 rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0);
323 CIFSSMBClose(xid, tcon, netfid);
324 return rc;
325}
326
327int
323check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 328check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
324 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, 329 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
325 const unsigned char *path) 330 const unsigned char *path)
@@ -553,8 +558,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
553 558
554 /* BB what if DFS and this volume is on different share? BB */ 559 /* BB what if DFS and this volume is on different share? BB */
555 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) 560 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
556 rc = create_mf_symlink(xid, pTcon, full_path, symname, 561 rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
557 cifs_sb);
558 else if (pTcon->unix_ext) 562 else if (pTcon->unix_ext)
559 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, 563 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
560 cifs_sb->local_nls); 564 cifs_sb->local_nls);
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 099c27602257..1470ec4fc39d 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -1010,6 +1010,7 @@ struct smb_version_operations smb1_operations = {
1010 .mand_unlock_range = cifs_unlock_range, 1010 .mand_unlock_range = cifs_unlock_range,
1011 .push_mand_locks = cifs_push_mandatory_locks, 1011 .push_mand_locks = cifs_push_mandatory_locks,
1012 .query_mf_symlink = cifs_query_mf_symlink, 1012 .query_mf_symlink = cifs_query_mf_symlink,
1013 .create_mf_symlink = cifs_create_mf_symlink,
1013 .is_read_op = cifs_is_read_op, 1014 .is_read_op = cifs_is_read_op,
1014}; 1015};
1015 1016