int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, bool excl) { int rc; unsigned int xid = get_xid(); /* * BB below access is probably too much for mknod to request * but we have to do query and setpathinfo so requesting * less could fail (unless we want to request getatr and setatr * permissions (only). At least for POSIX we do not have to * request so much. */ unsigned oflags = O_EXCL | O_CREAT | O_RDWR; struct tcon_link *tlink; struct cifs_tcon *tcon; struct TCP_Server_Info *server; struct cifs_fid fid; __u32 oplock; int created = FILE_CREATED; cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p\n", inode, direntry->d_name.name, direntry); tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb)); rc = PTR_ERR(tlink); if (IS_ERR(tlink)) goto out_free_xid; tcon = tlink_tcon(tlink); server = tcon->ses->server; if (server->ops->new_lease_key) server->ops->new_lease_key(&fid); rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, &oplock, &fid, &created); if (!rc && server->ops->close) server->ops->close(xid, tcon, &fid); cifs_put_tlink(tlink); out_free_xid: free_xid(xid); return rc; }
int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, bool excl) { int rc; unsigned int xid = get_xid(); /* * BB below access is probably too much for mknod to request * but we have to do query and setpathinfo so requesting * less could fail (unless we want to request getatr and setatr * permissions (only). At least for POSIX we do not have to * request so much. */ unsigned oflags = O_EXCL | O_CREAT | O_RDWR; struct tcon_link *tlink; __u16 fileHandle; __u32 oplock; int created = FILE_CREATED; cFYI(1, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p", inode, direntry->d_name.name, direntry); tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb)); rc = PTR_ERR(tlink); if (IS_ERR(tlink)) goto out_free_xid; rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, &oplock, &fileHandle, &created); if (!rc) CIFSSMBClose(xid, tlink_tcon(tlink), fileHandle); cifs_put_tlink(tlink); out_free_xid: free_xid(xid); return rc; }
int cifs_atomic_open(struct inode *inode, struct dentry *direntry, struct file *file, unsigned oflags, umode_t mode, int *opened) { int rc; unsigned int xid; struct tcon_link *tlink; struct cifs_tcon *tcon; struct TCP_Server_Info *server; struct cifs_fid fid; struct cifs_pending_open open; __u32 oplock; struct cifsFileInfo *file_info; /* * Posix open is only called (at lookup time) for file create now. For * opens (rather than creates), because we do not know if it is a file * or directory yet, and current Samba no longer allows us to do posix * open on dirs, we could end up wasting an open call on what turns out * to be a dir. For file opens, we wait to call posix open till * cifs_open. It could be added to atomic_open in the future but the * performance tradeoff of the extra network request when EISDIR or * EACCES is returned would have to be weighed against the 50% reduction * in network traffic in the other paths. */ if (!(oflags & O_CREAT)) { struct dentry *res; /* * Check for hashed negative dentry. We have already revalidated * the dentry and it is fine. No need to perform another lookup. */ if (!d_unhashed(direntry)) return -ENOENT; res = cifs_lookup(inode, direntry, 0); if (IS_ERR(res)) return PTR_ERR(res); return finish_no_open(file, res); } rc = check_name(direntry); if (rc) return rc; xid = get_xid(); cifs_dbg(FYI, "parent inode = 0x%p name is: %s and dentry = 0x%p\n", inode, direntry->d_name.name, direntry); tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb)); if (IS_ERR(tlink)) { rc = PTR_ERR(tlink); goto out_free_xid; } tcon = tlink_tcon(tlink); server = tcon->ses->server; if (server->ops->new_lease_key) server->ops->new_lease_key(&fid); cifs_add_pending_open(&fid, tlink, &open); rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, &oplock, &fid, opened); if (rc) { cifs_del_pending_open(&open); goto out; } rc = finish_open(file, direntry, generic_file_open, opened); if (rc) { if (server->ops->close) server->ops->close(xid, tcon, &fid); cifs_del_pending_open(&open); goto out; } file_info = cifs_new_fileinfo(&fid, file, tlink, oplock); if (file_info == NULL) { if (server->ops->close) server->ops->close(xid, tcon, &fid); cifs_del_pending_open(&open); fput(file); rc = -ENOMEM; } out: cifs_put_tlink(tlink); out_free_xid: free_xid(xid); return rc; }
int cifs_atomic_open(struct inode *inode, struct dentry *direntry, struct file *file, unsigned oflags, umode_t mode, int *opened) { int rc; unsigned int xid; struct tcon_link *tlink; struct cifs_tcon *tcon; __u16 fileHandle; __u32 oplock; struct cifsFileInfo *pfile_info; /* Posix open is only called (at lookup time) for file create now. For * opens (rather than creates), because we do not know if it is a file * or directory yet, and current Samba no longer allows us to do posix * open on dirs, we could end up wasting an open call on what turns out * to be a dir. For file opens, we wait to call posix open till * cifs_open. It could be added to atomic_open in the future but the * performance tradeoff of the extra network request when EISDIR or * EACCES is returned would have to be weighed against the 50% reduction * in network traffic in the other paths. */ if (!(oflags & O_CREAT)) { struct dentry *res = cifs_lookup(inode, direntry, 0); if (IS_ERR(res)) return PTR_ERR(res); return finish_no_open(file, res); } rc = check_name(direntry); if (rc) return rc; xid = get_xid(); cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p", inode, direntry->d_name.name, direntry); tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb)); if (IS_ERR(tlink)) goto out_free_xid; tcon = tlink_tcon(tlink); rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, &oplock, &fileHandle, opened); if (rc) goto out; rc = finish_open(file, direntry, generic_file_open, opened); if (rc) { CIFSSMBClose(xid, tcon, fileHandle); goto out; } pfile_info = cifs_new_fileinfo(fileHandle, file, tlink, oplock); if (pfile_info == NULL) { CIFSSMBClose(xid, tcon, fileHandle); rc = -ENOMEM; } out: cifs_put_tlink(tlink); out_free_xid: free_xid(xid); return rc; }