summaryrefslogtreecommitdiffstats
path: root/fs/ncpfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ncpfs')
-rw-r--r--fs/ncpfs/dir.c6
-rw-r--r--fs/ncpfs/file.c38
-rw-r--r--fs/ncpfs/inode.c19
-rw-r--r--fs/ncpfs/ioctl.c16
-rw-r--r--fs/ncpfs/mmap.c1
-rw-r--r--fs/ncpfs/ncplib_kernel.c24
-rw-r--r--fs/ncpfs/ncplib_kernel.h4
-rw-r--r--fs/ncpfs/symlink.c56
8 files changed, 90 insertions, 74 deletions
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 55daea198..11694e79b 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -973,7 +973,7 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
/*
* Check whether to close the file ...
*/
- if (inode && NCP_FINFO(inode)->opened) {
+ if (inode) {
PPRINTK("ncp_unlink: closing file\n");
ncp_make_closed(inode);
}
@@ -982,7 +982,7 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
#ifdef CONFIG_NCPFS_STRONG
/* 9C is Invalid path.. It should be 8F, 90 - read only, but
it is not :-( */
- if (error == 0x9C && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
+ if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
error = ncp_force_unlink(dir, dentry);
}
#endif
@@ -1051,7 +1051,7 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
new_dir, __new_name);
#ifdef CONFIG_NCPFS_STRONG
- if ((error == 0x90 || error == -EACCES) &&
+ if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
server->m.flags & NCP_MOUNT_STRONG) { /* RO */
error = ncp_force_rename(old_dir, old_dentry, __old_name,
new_dir, new_dentry, __new_name);
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 6f8fd2d63..3442c3f9f 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -26,7 +26,7 @@ static inline unsigned int min(unsigned int a, unsigned int b)
return a < b ? a : b;
}
-static int ncp_fsync(struct file *file, struct dentry *dentry)
+static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync)
{
return 0;
}
@@ -46,12 +46,12 @@ int ncp_make_open(struct inode *inode, int right)
}
DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n",
- NCP_FINFO(inode)->opened,
+ atomic_read(&NCP_FINFO(inode)->opened),
NCP_FINFO(inode)->volNumber,
NCP_FINFO(inode)->dirEntNum);
error = -EACCES;
- lock_super(inode->i_sb);
- if (!NCP_FINFO(inode)->opened) {
+ down(&NCP_FINFO(inode)->open_sem);
+ if (!atomic_read(&NCP_FINFO(inode)->opened)) {
struct ncp_entry_info finfo;
int result;
@@ -88,15 +88,18 @@ int ncp_make_open(struct inode *inode, int right)
*/
update:
ncp_update_inode(inode, &finfo);
+ atomic_set(&NCP_FINFO(inode)->opened, 1);
}
access = NCP_FINFO(inode)->access;
PPRINTK("ncp_make_open: file open, access=%x\n", access);
- if (access == right || access == O_RDWR)
+ if (access == right || access == O_RDWR) {
+ atomic_inc(&NCP_FINFO(inode)->opened);
error = 0;
+ }
out_unlock:
- unlock_super(inode->i_sb);
+ up(&NCP_FINFO(inode)->open_sem);
out:
return error;
}
@@ -153,7 +156,7 @@ ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
freelen = ncp_read_bounce_size(bufsize);
freepage = kmalloc(freelen, GFP_NFS);
if (!freepage)
- goto out;
+ goto outrel;
error = 0;
/* First read in as much as possible for each bufsize. */
while (already_read < count) {
@@ -166,9 +169,8 @@ ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
pos, to_read, buf, &read_this_time,
freepage, freelen);
if (error) {
- kfree(freepage);
- error = -EIO; /* This is not exact, i know.. */
- goto out;
+ error = -EIO; /* NW errno -> Linux errno */
+ break;
}
pos += read_this_time;
buf += read_this_time;
@@ -188,6 +190,8 @@ ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
DPRINTK("ncp_file_read: exit %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
+outrel:
+ ncp_inode_close(inode);
out:
return already_read ? already_read : error;
}
@@ -236,8 +240,10 @@ ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
already_written = 0;
bouncebuffer = kmalloc(bufsize, GFP_NFS);
- if (!bouncebuffer)
- return -EIO; /* -ENOMEM */
+ if (!bouncebuffer) {
+ errno = -EIO; /* -ENOMEM */
+ goto outrel;
+ }
while (already_written < count) {
int written_this_time;
size_t to_write = min(bufsize - (pos % bufsize),
@@ -271,15 +277,15 @@ ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
}
DPRINTK("ncp_file_write: exit %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
+outrel:
+ ncp_inode_close(inode);
out:
return already_written ? already_written : errno;
}
static int ncp_release(struct inode *inode, struct file *file) {
- if (NCP_FINFO(inode)->opened) {
- if (ncp_make_closed(inode)) {
- DPRINTK("ncp_release: failed to close\n");
- }
+ if (ncp_make_closed(inode)) {
+ DPRINTK("ncp_release: failed to close\n");
}
return 0;
}
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index f6ff5e420..cff9649f5 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -31,14 +31,13 @@
#include "ncplib_kernel.h"
-static void ncp_put_inode(struct inode *);
static void ncp_delete_inode(struct inode *);
static void ncp_put_super(struct super_block *);
static int ncp_statfs(struct super_block *, struct statfs *);
static struct super_operations ncp_sops =
{
- put_inode: ncp_put_inode,
+ put_inode: force_delete,
delete_inode: ncp_delete_inode,
put_super: ncp_put_super,
statfs: ncp_statfs,
@@ -62,7 +61,6 @@ void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
#ifdef CONFIG_NCPFS_STRONG
NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
#endif
- NCP_FINFO(inode)->opened = nwinfo->opened;
NCP_FINFO(inode)->access = nwinfo->access;
NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
@@ -77,7 +75,7 @@ void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
struct nw_info_struct *nwi = &nwinfo->i;
struct ncp_server *server = NCP_SERVER(inode);
- if (!NCP_FINFO(inode)->opened) {
+ if (!atomic_read(&NCP_FINFO(inode)->opened)) {
#ifdef CONFIG_NCPFS_STRONG
NCP_FINFO(inode)->nwattr = nwi->attributes;
#endif
@@ -217,6 +215,9 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
inode = get_empty_inode();
if (inode) {
+ init_MUTEX(&NCP_FINFO(inode)->open_sem);
+ atomic_set(&NCP_FINFO(inode)->opened, info->opened);
+
inode->i_sb = sb;
inode->i_dev = sb->s_dev;
inode->i_ino = info->ino;
@@ -239,12 +240,6 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
return inode;
}
-static void ncp_put_inode(struct inode *inode)
-{
- if (inode->i_count == 1)
- inode->i_nlink = 0;
-}
-
static void
ncp_delete_inode(struct inode *inode)
{
@@ -252,7 +247,7 @@ ncp_delete_inode(struct inode *inode)
DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
}
- if (NCP_FINFO(inode)->opened && ncp_make_closed(inode) != 0) {
+ if (ncp_make_closed(inode) != 0) {
/* We can't do anything but complain. */
printk(KERN_ERR "ncp_delete_inode: could not close\n");
}
@@ -325,7 +320,6 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_blocksize = 1024; /* Eh... Is this correct? */
sb->s_blocksize_bits = 10;
sb->s_magic = NCP_SUPER_MAGIC;
- sb->s_dev = dev;
sb->s_op = &ncp_sops;
server = NCP_SBP(sb);
@@ -683,6 +677,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
/* According to ndir, the changes only take effect after
closing the file */
+ ncp_inode_close(inode);
result = ncp_make_closed(inode);
if (!result)
vmtruncate(inode, attr->ia_size);
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 26c95fc8f..24e616396 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -335,18 +335,12 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{
return result;
}
+ result = -EIO;
if (!ncp_conn_valid(server))
- {
- return -EIO;
- }
+ goto outrel;
+ result = -EISDIR;
if (!S_ISREG(inode->i_mode))
- {
- return -EISDIR;
- }
- if (!NCP_FINFO(inode)->opened)
- {
- return -EBADFD;
- }
+ goto outrel;
if (rqdata.cmd == NCP_LOCK_CLEAR)
{
result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
@@ -373,6 +367,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
rqdata.timeout);
if (result > 0) result = -EAGAIN;
}
+outrel:
+ ncp_inode_close(inode);
return result;
}
#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
index 752ae1e1e..08d28d895 100644
--- a/fs/ncpfs/mmap.c
+++ b/fs/ncpfs/mmap.c
@@ -82,6 +82,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
break;
}
}
+ ncp_inode_close(inode);
}
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index 73afd107a..0353882b9 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -221,20 +221,23 @@ ncp_close_file(struct ncp_server *server, const char *file_id)
return result;
}
-/*
- * Called with the superblock locked.
- */
int
ncp_make_closed(struct inode *inode)
{
int err;
- NCP_FINFO(inode)->opened = 0;
- err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle);
- if (!err)
- PPRINTK("ncp_make_closed: volnum=%d, dirent=%u, error=%d\n",
- NCP_FINFO(inode)->volNumber,
- NCP_FINFO(inode)->dirEntNum, err);
+ err = 0;
+ down(&NCP_FINFO(inode)->open_sem);
+ if (atomic_read(&NCP_FINFO(inode)->opened) == 1) {
+ atomic_set(&NCP_FINFO(inode)->opened, 0);
+ err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle);
+
+ if (!err)
+ PPRINTK("ncp_make_closed: volnum=%d, dirent=%u, error=%d\n",
+ NCP_FINFO(inode)->volNumber,
+ NCP_FINFO(inode)->dirEntNum, err);
+ }
+ up(&NCP_FINFO(inode)->open_sem);
return err;
}
@@ -613,7 +616,8 @@ int ncp_open_create_file_or_subdir(struct ncp_server *server,
if ((result = ncp_request(server, 87)) != 0)
goto out;
- target->opened = 1;
+ if (!(create_attributes & aDIR))
+ target->opened = 1;
target->server_file_handle = ncp_reply_dword(server, 0);
target->open_create_action = ncp_reply_byte(server, 4);
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 8b33a5c2e..31797a3c3 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -57,6 +57,10 @@ int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16,
int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16,
const char *, int *);
+static inline void ncp_inode_close(struct inode *inode) {
+ atomic_dec(&NCP_FINFO(inode)->opened);
+}
+
int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
struct nw_info_struct *target);
int ncp_lookup_volume(struct ncp_server *, char *, struct nw_info_struct *);
diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
index 46925eb6d..0962593da 100644
--- a/fs/ncpfs/symlink.c
+++ b/fs/ncpfs/symlink.c
@@ -50,10 +50,6 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
char *link;
char *buf = (char*)kmap(page);
- error = -EIO;
- if (ncp_make_open(inode,O_RDONLY))
- goto fail;
-
error = -ENOMEM;
for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) {
if (cnt > 10)
@@ -61,20 +57,22 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
schedule();
}
+ if (ncp_make_open(inode,O_RDONLY))
+ goto failEIO;
+
error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
0,NCP_MAX_SYMLINK_SIZE,link,&length);
- if (error) {
- kfree(link);
- goto fail;
- }
+ ncp_inode_close(inode);
+ /* Close file handle if no other users... */
+ ncp_make_closed(inode);
+ if (error)
+ goto failEIO;
+
if (length<NCP_MIN_SYMLINK_SIZE ||
((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||
- ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
- error = -EIO;
- kfree(link);
- goto fail;
- }
+ ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1)
+ goto failEIO;
len = NCP_MAX_SYMLINK_SIZE;
error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0);
@@ -86,6 +84,9 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
UnlockPage(page);
return 0;
+failEIO:
+ error = -EIO;
+ kfree(link);
fail:
SetPageError(page);
kunmap(page);
@@ -120,13 +121,15 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL)
return -ENOMEM;
- if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN)) {
- kfree(link);
- return -EIO;
- }
+ err = -EIO;
+ if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN))
+ goto failfree;
inode=dentry->d_inode;
+ if (ncp_make_open(inode, O_WRONLY))
+ goto failfree;
+
((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0;
((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1;
@@ -134,19 +137,26 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
symlink can point out of ncp filesystem */
length += 1;
err = ncp_io2vol(NCP_SERVER(inode),link+8,&length,symname,length-1,0);
- if (err) {
- kfree(link);
- return err;
- }
+ if (err)
+ goto fail;
if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
0, length+8, link, &i) || i!=length+8) {
- kfree(link);
- return -EIO;
+ err = -EIO;
+ goto fail;
}
+ ncp_inode_close(inode);
+ ncp_make_closed(inode);
kfree(link);
return 0;
+
+fail:
+ ncp_inode_close(inode);
+ ncp_make_closed(inode);
+failfree:
+ kfree(link);
+ return err;
}
#endif