summaryrefslogtreecommitdiffstats
path: root/fs/smbfs/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/smbfs/proc.c')
-rw-r--r--fs/smbfs/proc.c442
1 files changed, 274 insertions, 168 deletions
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index 311457a74..57b4be6fb 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -29,7 +29,12 @@
#define SMB_DIRINFO_SIZE 43
#define SMB_STATUS_SIZE 21
+#define SMBFS_PARANOIA 1
+/* #define SMBFS_DEBUG_VERBOSE 1 */
+/* #define pr_debug printk */
+
static int smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc);
+void smb_close_socket(struct smb_sb_info *);
static inline int
min(int a, int b)
@@ -79,6 +84,15 @@ smb_encode_smb_length(__u8 * p, __u32 len)
return p + 4;
}
+/*
+ * Return the server for the specified dentry
+ * N.B. Make this a #define in the smb header
+ */
+static struct smb_sb_info * server_from_dentry(struct dentry * dentry)
+{
+ return &dentry->d_sb->u.smbfs_sb;
+}
+
static int smb_d_path(struct dentry * entry, char * buf)
{
if (IS_ROOT(entry)) {
@@ -283,11 +297,15 @@ smb_errno(int errcls, int error)
return EEXIST;
case 87:
return 0; /* Unknown error!! */
+ case 123: /* Invalid name?? e.g. .tmp* */
+ return ENOENT;
/* This next error seems to occur on an mv when
* the destination exists */
case 183:
return EEXIST;
default:
+ printk("smb_errno: ERRDOS code %d, returning EIO\n",
+ error);
return EIO;
} else if (errcls == ERRSRV)
switch (error)
@@ -301,6 +319,8 @@ smb_errno(int errcls, int error)
case ERRaccess:
return EACCES;
default:
+ printk("smb_errno: ERRSRV code %d, returning EIO\n",
+ error);
return EIO;
} else if (errcls == ERRHRD)
switch (error)
@@ -322,9 +342,14 @@ smb_errno(int errcls, int error)
case ERRlock:
return EDEADLK;
default:
+ printk("smb_errno: ERRHRD code %d, returning EIO\n",
+ error);
return EIO;
} else if (errcls == ERRCMD)
+ {
+ printk("smb_errno: ERRCMD code %d, returning EIO\n", error);
return EIO;
+ }
return 0;
}
@@ -349,6 +374,7 @@ static int
smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc)
{
int result = 0;
+
s->rcls = 0;
s->err = 0;
@@ -371,86 +397,133 @@ smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc)
return result;
}
-/* smb_retry: This function should be called when smb_request_ok has
+/*
+ * smb_retry: This function should be called when smb_request_ok has
indicated an error. If the error was indicated because the
connection was killed, we try to reconnect. If smb_retry returns 0,
the error was indicated for another reason, so a retry would not be
- of any use. */
+ of any use.
+ * N.B. The server must be locked for this call.
+ */
static int
smb_retry(struct smb_sb_info *server)
{
+ int result = 0;
+
if (server->state != CONN_INVALID)
- {
- return 0;
- }
- if (server->sock_file != NULL)
- {
- close_fp(server->sock_file);
- server->sock_file = NULL;
- }
+ goto out;
+
+ smb_close_socket(server);
if (server->conn_pid == 0)
{
+ printk("smb_retry: no connection process\n");
server->state = CONN_RETRIED;
- return 0;
+ goto out;
}
+ printk("smb_retry: signalling process %d\n", server->conn_pid);
kill_proc(server->conn_pid, SIGUSR1, 0);
server->conn_pid = 0;
+ /*
+ * Block here until we get a new connection.
+ * N.B. This needs to be fixed ... we should wait in an
+ * interruptible sleep for CONN_VALID.
+ */
+ printk("smb_retry: blocking for new connection\n");
smb_lock_server(server);
- if (server->sock_file != NULL)
+ if (server->state == CONN_VALID)
{
- server->state = CONN_VALID;
- return 1;
+ printk("smb_retry: new connection pid=%d\n", server->conn_pid);
+ result = 1;
}
- return 0;
+out:
+ return result;
}
+/*
+ * This is called with the server locked after a successful smb_newconn().
+ * It installs the new connection pid, sets server->state to CONN_VALID,
+ * and unlocks the server.
+ * N.B. The first call is made without locking the server -- need to fix!
+ */
int
smb_offerconn(struct smb_sb_info *server)
{
+ int error;
+
+ error = -EACCES;
if (!suser() && (current->uid != server->m.mounted_uid))
- {
- return -EACCES;
- }
+ goto out;
+
server->conn_pid = current->pid;
- return 0;
+ server->state = CONN_VALID;
+ printk("smb_offerconn: state valid, pid=%d\n", server->conn_pid);
+ error = 0;
+
+ /*
+ * The initial call may be made without the server locked?
+ */
+out:
+ if (atomic_read(&server->sem.count) != 1)
+ smb_unlock_server(server);
+ else
+ printk("smb_offerconn: server not locked, count=%d\n",
+ atomic_read(&server->sem.count));
+ return error;
}
+/*
+ * This must be called with the server locked.
+ * N.B. The first call is made without locking the server -- need to fix!
+ */
int
smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
{
struct file *filp;
+ int error;
+ error = -EBADF;
if (opt->fd >= NR_OPEN || !(filp = current->files->fd[opt->fd]))
- {
- return -EBADF;
- }
+ goto out_unlock;
if (!S_ISSOCK(filp->f_dentry->d_inode->i_mode))
- {
- return -EBADF;
- }
+ goto out_unlock;
+ if (!S_ISSOCK(filp->f_dentry->d_inode->i_mode))
+ goto out_unlock;
+
+ error = -EACCES;
if (!suser() && (current->uid != server->m.mounted_uid))
- {
- return -EACCES;
- }
- if (server->sock_file != NULL)
- {
- close_fp(server->sock_file);
- server->sock_file = NULL;
- }
+ goto out_unlock;
+
+ /*
+ * Make sure the old socket is closed
+ */
+ smb_close_socket(server);
+
filp->f_count += 1;
server->sock_file = filp;
smb_catch_keepalive(server);
server->opt = *opt;
pr_debug("smb_newconn: protocol = %d\n", server->opt.protocol);
- server->conn_pid = 0;
server->generation += 1;
- smb_unlock_server(server);
- return 0;
+ error = 0;
+
+out:
+ return error;
+
+ /*
+ * Unlock now if an error occurred.
+ */
+out_unlock:
+ if (atomic_read(&server->sem.count) != 1)
+ smb_unlock_server(server);
+ else
+ printk("smb_newconn: server not locked, count=%d\n",
+ atomic_read(&server->sem.count));
+ goto out;
}
/* smb_setup_header: We completely set up the packet. You only have to
@@ -503,17 +576,15 @@ smb_setup_bcc(struct smb_sb_info *server, __u8 * p)
SMB_HEADER_LEN + 2 * SMB_WCT(packet) - 2 + bcc);
}
-
/*
* We're called with the server locked, and we leave it that way. We
* try maximum permissions.
*/
static int
-smb_proc_open(struct dentry *dir)
+smb_proc_open(struct smb_sb_info *server, struct dentry *dir)
{
struct inode *ino = dir->d_inode;
- struct smb_sb_info *server = SMB_SERVER(ino);
int error;
char *p;
@@ -532,7 +603,7 @@ smb_proc_open(struct dentry *dir)
if ((error != -EACCES) && (error != -ETXTBSY)
&& (error != -EROFS))
- return error;
+ goto out;
p = smb_setup_header(server, SMBopen, 2, 0);
WSET(server->packet, smb_vwv0, 0x40); /* read only */
@@ -545,40 +616,56 @@ smb_proc_open(struct dentry *dir)
{
if (smb_retry(server))
goto retry;
-
- return error;
+ goto out;
}
}
/* We should now have data in vwv[0..6]. */
ino->u.smbfs_i.fileid = WVAL(server->packet, smb_vwv0);
- ino->u.smbfs_i.attr = WVAL(server->packet, smb_vwv1);
+ ino->u.smbfs_i.attr = WVAL(server->packet, smb_vwv1);
ino->u.smbfs_i.access = WVAL(server->packet, smb_vwv6);
ino->u.smbfs_i.access &= 3;
ino->u.smbfs_i.open = server->generation;
pr_debug("smb_proc_open: entry->access = %d\n", ino->u.smbfs_i.access);
- return 0;
+out:
+ return error;
}
int
smb_open(struct dentry *dir, int wish)
{
- struct inode *i=dir->d_inode;
- struct smb_sb_info *server = SMB_SERVER(i);
- int result = -EACCES;
+ struct inode *i = dir->d_inode;
+ int result;
- smb_lock_server(server);
+ result = -EIO;
+ if (!i)
+ {
+ printk("smb_open: no inode for dentry %s/%s\n",
+ dir->d_parent->d_name.name, dir->d_name.name);
+ goto out;
+ }
- if (!smb_is_open(i)) {
- int error = smb_proc_open(dir);
- if (error) {
- smb_unlock_server(server);
- return error;
+ /*
+ * If the inode is already open, we don't need to lock the server.
+ */
+ if (!smb_is_open(i))
+ {
+ struct smb_sb_info *server = SMB_SERVER(i);
+ smb_lock_server(server);
+ result = smb_proc_open(server, dir);
+ smb_unlock_server(server);
+ if (result)
+ {
+ printk("smb_open: %s/%s open failed, result=%d\n",
+ dir->d_parent->d_name.name, dir->d_name.name,
+ result);
+ goto out;
}
}
+ result = -EACCES;
if (((wish == O_RDONLY) && ((i->u.smbfs_i.access == O_RDONLY)
|| (i->u.smbfs_i.access == O_RDWR)))
|| ((wish == O_WRONLY) && ((i->u.smbfs_i.access == O_WRONLY)
@@ -586,7 +673,7 @@ smb_open(struct dentry *dir, int wish)
|| ((wish == O_RDWR) && (i->u.smbfs_i.access == O_RDWR)))
result = 0;
- smb_unlock_server(server);
+out:
return result;
}
@@ -600,24 +687,21 @@ static int smb_proc_close(struct smb_sb_info *server,
DSET(server->packet, smb_vwv1, mtime);
return smb_request_ok(server, SMBclose, 0, 0);
}
-
-int smb_close(struct dentry *dir)
+int
+smb_close(struct inode *ino)
{
- struct inode *ino = dir->d_inode;
- struct smb_sb_info *server = SMB_SERVER(ino);
- int result;
-
- smb_lock_server(server);
+ int result = 0;
- if (!smb_is_open(ino)) {
+ if (smb_is_open(ino))
+ {
+ struct smb_sb_info *server = SMB_SERVER(ino);
+ smb_lock_server(server);
+ result = smb_proc_close(server, ino->u.smbfs_i.fileid,
+ ino->i_mtime);
smb_unlock_server(server);
- return 0;
+ ino->u.smbfs_i.open = 0;
}
-
- result = smb_proc_close(server, ino->u.smbfs_i.fileid, ino->i_mtime);
- ino->u.smbfs_i.open = 0;
- smb_unlock_server(server);
return result;
}
@@ -633,38 +717,49 @@ smb_proc_read(struct inode *ino, off_t offset, long count, char *data)
struct smb_sb_info *server = SMB_SERVER(ino);
__u16 returned_count, data_len;
char *buf;
- int error;
+ int result;
+ struct dentry * dentry;
+
+ if (!ino || !(dentry = ino->u.smbfs_i.dentry))
+ {
+ printk("smb_proc_read: no inode!\n");
+ return -EIO;
+ }
smb_lock_server(server);
smb_setup_header(server, SMBread, 5, 0);
- buf = server->packet;
+ /* Achtung! Do not refer to the cached packet after the request! */
+ buf = server->packet;
WSET(buf, smb_vwv0, ino->u.smbfs_i.fileid);
WSET(buf, smb_vwv1, count);
DSET(buf, smb_vwv2, offset);
WSET(buf, smb_vwv4, 0);
- if ((error = smb_request_ok(server, SMBread, 5, -1)) < 0)
- {
- smb_unlock_server(server);
- return error;
- }
- returned_count = WVAL(buf, smb_vwv0);
+ result = smb_request_ok(server, SMBread, 5, -1);
+ if (result < 0)
+ goto out;
+#if 0
+printk("smb_proc_read: file %s/%s, result=%d, packet=%p\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, result, server->packet);
+#endif
+ returned_count = WVAL(server->packet, smb_vwv0);
buf = SMB_BUF(server->packet);
data_len = WVAL(buf, 1);
-
memcpy(data, buf+3, data_len);
- smb_unlock_server(server);
-
if (returned_count != data_len)
{
printk(KERN_NOTICE "smb_proc_read: returned != data_len\n");
printk(KERN_NOTICE "smb_proc_read: ret_c=%d, data_len=%d\n",
returned_count, data_len);
}
- return data_len;
+ result = data_len;
+
+out:
+ smb_unlock_server(server);
+ return result;
}
int
@@ -697,18 +792,17 @@ int
smb_proc_create(struct dentry *dir, struct qstr *name,
__u16 attr, time_t ctime)
{
+ struct smb_sb_info *server;
int error;
char *p;
- struct inode *i=dir->d_inode;
- struct smb_sb_info *server = SMB_SERVER(i);
- char *buf;
+ server = server_from_dentry(dir);
smb_lock_server(server);
+
retry:
- buf = server->packet;
p = smb_setup_header(server, SMBcreate, 3, 0);
- WSET(buf, smb_vwv0, attr);
- DSET(buf, smb_vwv1, utc2local(ctime));
+ WSET(server->packet, smb_vwv0, attr);
+ DSET(server->packet, smb_vwv1, utc2local(ctime));
*p++ = 4;
p = smb_encode_path(server, p, dir, name);
smb_setup_bcc(server, p);
@@ -719,23 +813,25 @@ smb_proc_create(struct dentry *dir, struct qstr *name,
{
goto retry;
}
- smb_unlock_server(server);
- return error;
+ goto out;
}
- smb_proc_close(server, WVAL(buf, smb_vwv0), CURRENT_TIME);
- smb_unlock_server(server);
+ smb_proc_close(server, WVAL(server->packet, smb_vwv0), CURRENT_TIME);
+ error = 0;
- return 0;
+out:
+ smb_unlock_server(server);
+ return error;
}
int
smb_proc_mv(struct dentry *odir, struct qstr *oname,
struct dentry *ndir, struct qstr *nname)
{
+ struct smb_sb_info *server;
char *p;
- struct smb_sb_info *server = SMB_SERVER(odir->d_inode);
int result;
+ server = server_from_dentry(odir);
smb_lock_server(server);
retry:
@@ -761,10 +857,11 @@ smb_proc_mv(struct dentry *odir, struct qstr *oname,
int
smb_proc_mkdir(struct dentry *dir, struct qstr *name)
{
+ struct smb_sb_info *server;
char *p;
int result;
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
+ server = server_from_dentry(dir);
smb_lock_server(server);
retry:
@@ -787,10 +884,11 @@ smb_proc_mkdir(struct dentry *dir, struct qstr *name)
int
smb_proc_rmdir(struct dentry *dir, struct qstr *name)
{
+ struct smb_sb_info *server;
char *p;
int result;
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
+ server = server_from_dentry(dir);
smb_lock_server(server);
retry:
@@ -813,10 +911,11 @@ smb_proc_rmdir(struct dentry *dir, struct qstr *name)
int
smb_proc_unlink(struct dentry *dir, struct qstr *name)
{
+ struct smb_sb_info *server;
char *p;
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
int result;
+ server = server_from_dentry(dir);
smb_lock_server(server);
retry:
@@ -882,22 +981,18 @@ smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
static void
smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
{
+ fattr->f_mode = server->m.file_mode;
if (fattr->attr & aDIR)
{
fattr->f_mode = server->m.dir_mode;
fattr->f_size = 512;
- } else
- {
- fattr->f_mode = server->m.file_mode;
}
+ fattr->f_blocks = 0; /* already set to zero? */
if ((fattr->f_blksize != 0) && (fattr->f_size != 0))
{
fattr->f_blocks =
(fattr->f_size - 1) / fattr->f_blksize + 1;
- } else
- {
- fattr->f_blocks = 0;
}
return;
}
@@ -982,13 +1077,13 @@ smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos,
smb_lock_server(server);
retry:
- buf = server->packet;
first = 1;
total_count = 0;
current_entry = entry;
while (1)
{
+ buf = server->packet;
if (first == 1)
{
p = smb_setup_header(server, SMBsearch, 2, 0);
@@ -1098,6 +1193,7 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
struct smb_dirent *entry, int level)
{
char *result;
+ unsigned int len;
smb_init_dirent(server, &(entry->attr));
@@ -1105,20 +1201,24 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
{
/* We might add more levels later... */
case 1:
- entry->len = *(p+26);
- strncpy(entry->name, p + 27, entry->len);
- entry->name[entry->len] = '\0';
- entry->attr.f_size = DVAL(p, 16);
- entry->attr.attr = *(p+24);
-
entry->attr.f_ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4));
entry->attr.f_atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8));
entry->attr.f_mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12));
- result = p + 28 + *(p+26);
+ entry->attr.f_size = DVAL(p, 16);
+ entry->attr.attr = *(p+24);
+ /*
+ * Achtung, lengths can go up to 255
+ */
+ len = *((unsigned char *) p + 26);
+ entry->len = len;
+ strncpy(entry->name, p + 27, len);
+ entry->name[len] = '\0';
+
+ result = p + 28 + len;
break;
default:
- pr_debug("Unknown long filename format %d\n", level);
+ printk("smb_decode: Unknown long filename format %d\n", level);
result = p + WVAL(p, 0);
}
@@ -1135,6 +1235,7 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p,
}
smb_finish_dirent(server, &(entry->attr));
+
return result;
}
@@ -1148,7 +1249,7 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
char *p;
char *lastname;
- int lastname_len;
+ unsigned lastname_len;
int i;
int first, entries, entries_seen;
@@ -1168,7 +1269,7 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
int ff_dir_handle = 0;
int loop_count = 0;
- char param[SMB_MAXPATHLEN + 2 + 12];
+ char param[SMB_MAXPATHLEN + 2 + 12]; /* too long for the stack! */
int mask_len;
char *mask = &(param[12]);
@@ -1197,6 +1298,7 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
{
printk(KERN_WARNING "smb_proc_readdir_long: "
"Looping in FIND_NEXT??\n");
+ entries = -EIO;
break;
}
if (first != 0)
@@ -1243,15 +1345,23 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
{
goto retry;
}
- pr_debug("smb_proc_readdir_long: "
- "got error from trans2_request\n");
+#ifdef SMBFS_PARANOIA
+printk("smb_proc_readdir_long: trans2_request error=%d\n", result);
+#endif
+ entries = result;
break;
}
if (server->rcls != 0)
- {
- result = -EIO;
+ {
+#ifdef SMBFS_PARANOIA
+printk("smb_proc_readdir_long: error, rcls=%d, err=%d\n",
+server->rcls, server->err);
+#endif
+ /* Why isn't this considered an error? */
+ /* entries = -EIO; */
break;
}
+
/* parse out some important return info */
if (first != 0)
{
@@ -1278,17 +1388,15 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
lastname_len = 0;
if (ff_lastname > 0)
{
+ ff_resume_key = 0;
+ lastname = p + ff_lastname;
switch (info_level)
{
case 260:
- lastname = p + ff_lastname;
lastname_len = resp_data_len - ff_lastname;
- ff_resume_key = 0;
break;
case 1:
- lastname = p + ff_lastname + 1;
- lastname_len = *(p+ff_lastname);
- ff_resume_key = 0;
+ lastname_len = *((unsigned char *) lastname++);
break;
}
}
@@ -1320,11 +1428,12 @@ smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
entry->f_pos = entries_seen;
entries += 1;
}
- if (entries >= cache_size)
- {
- goto finished;
- }
entries_seen += 1;
+ if (entries < cache_size)
+ continue;
+
+ /* cache is full */
+ goto finished;
}
pr_debug("received %d entries (eos=%d resume=%d)\n",
@@ -1342,8 +1451,9 @@ int
smb_proc_readdir(struct dentry *dir, int fpos,
int cache_size, struct smb_dirent *entry)
{
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
+ struct smb_sb_info *server;
+ server = server_from_dentry(dir);
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
return smb_proc_readdir_long(server, dir, fpos, cache_size,
entry);
@@ -1353,18 +1463,15 @@ smb_proc_readdir(struct dentry *dir, int fpos,
}
static int
-smb_proc_getattr_core(struct dentry *dir, struct qstr *name,
- struct smb_fattr *attr)
+smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
+ struct qstr *name, struct smb_fattr *attr)
{
int result;
char *p;
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
- char *buf;
smb_lock_server(server);
retry:
- buf = server->packet;
p = smb_setup_header(server, SMBgetatr, 0, 0);
*p++ = 4;
p = smb_encode_path(server, p, dir, name);
@@ -1373,26 +1480,24 @@ smb_proc_getattr_core(struct dentry *dir, struct qstr *name,
if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0)
{
if (smb_retry(server))
- {
goto retry;
- }
- smb_unlock_server(server);
- return result;
+ goto out;
}
- attr->attr = WVAL(buf, smb_vwv0);
- attr->f_ctime = attr->f_atime =
- attr->f_mtime = local2utc(DVAL(buf, smb_vwv1));
+ attr->attr = WVAL(server->packet, smb_vwv0);
+ attr->f_ctime = attr->f_atime = attr->f_mtime =
+ local2utc(DVAL(server->packet, smb_vwv1));
+ attr->f_size = DVAL(server->packet, smb_vwv3);
+ result = 0;
- attr->f_size = DVAL(buf, smb_vwv3);
+out:
smb_unlock_server(server);
- return 0;
+ return result;
}
static int
-smb_proc_getattr_trans2(struct dentry *dir, struct qstr *name,
- struct smb_fattr *attr)
+smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
+ struct qstr *name, struct smb_fattr *attr)
{
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
char param[SMB_MAXPATHLEN + 20];
char *p;
int result;
@@ -1412,26 +1517,22 @@ smb_proc_getattr_trans2(struct dentry *dir, struct qstr *name,
0, NULL, p - param, param,
&resp_data_len, &resp_data,
&resp_param_len, &resp_param);
-
+
if (server->rcls != 0)
{
- smb_unlock_server(server);
- return -smb_errno(server->rcls, server->err);
+ result = -smb_errno(server->rcls, server->err);
+ goto out;
}
if (result < 0)
{
if (smb_retry(server))
- {
goto retry;
- }
- smb_unlock_server(server);
- return result;
+ goto out;
}
+ result = -ENOENT;
if (resp_data_len < 22)
- {
- smb_unlock_server(server);
- return -ENOENT;
- }
+ goto out;
+
attr->f_ctime = date_dos2unix(WVAL(resp_data, 2),
WVAL(resp_data, 0));
attr->f_atime = date_dos2unix(WVAL(resp_data, 6),
@@ -1440,24 +1541,28 @@ smb_proc_getattr_trans2(struct dentry *dir, struct qstr *name,
WVAL(resp_data, 8));
attr->f_size = DVAL(resp_data, 12);
attr->attr = WVAL(resp_data, 20);
- smb_unlock_server(server);
+ result = 0;
- return 0;
+out:
+ smb_unlock_server(server);
+ return result;
}
-int smb_proc_getattr(struct dentry *dir, struct qstr *name,
+int
+smb_proc_getattr(struct dentry *dir, struct qstr *name,
struct smb_fattr *fattr)
{
- struct smb_sb_info *server = SMB_SERVER(dir->d_inode);
- int result = 0;
+ struct smb_sb_info *server;
+ int result = -1;
+ server = server_from_dentry(dir);
smb_init_dirent(server, fattr);
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
- result = smb_proc_getattr_trans2(dir, name, fattr);
+ result = smb_proc_getattr_trans2(server, dir, name, fattr);
- if ((server->opt.protocol < SMB_PROTOCOL_LANMAN2) || (result < 0))
- result = smb_proc_getattr_core(dir, name, fattr);
+ if (result < 0)
+ result = smb_proc_getattr_core(server, dir, name, fattr);
smb_finish_dirent(server, fattr);
@@ -1546,12 +1651,12 @@ int
smb_proc_setattr(struct smb_sb_info *server, struct dentry *dir,
struct smb_fattr *fattr)
{
- int result;
+ int result = -1;
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
result = smb_proc_setattr_trans2(server, dir, fattr);
- if ((server->opt.protocol < SMB_PROTOCOL_LANMAN2) || (result < 0))
+ if (result < 0)
result = smb_proc_setattr_core(server, dir, fattr);
return result;
@@ -1560,9 +1665,9 @@ smb_proc_setattr(struct smb_sb_info *server, struct dentry *dir,
int
smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
{
+ struct smb_sb_info *server = &(sb->u.smbfs_sb);
int error;
char *p;
- struct smb_sb_info *server = &(sb->u.smbfs_sb);
smb_lock_server(server);
@@ -1573,16 +1678,17 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
{
if (smb_retry(server))
goto retry;
-
- smb_unlock_server(server);
- return error;
+ goto out;
}
p = SMB_VWV(server->packet);
attr->f_bsize = WVAL(p, 2) * WVAL(p, 4);
attr->f_blocks = WVAL(p, 0);
attr->f_bavail = attr->f_bfree = WVAL(p, 6);
+ error = 0;
+
+out:
smb_unlock_server(server);
- return 0;
+ return error;
}
int